From cee7b344da940e18a187e0eea334780aa53cfe5f Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Tue, 11 Feb 2025 18:14:49 +0100 Subject: [PATCH] Revert "vendor: github.com/docker/docker/v28.0.0-rc.1" This reverts commit b195b80ddf47e4f7391bae7350aecbb19ac5998d. Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- build/build.go | 2 +- commands/build.go | 4 +- driver/docker-container/driver.go | 5 +- go.mod | 4 +- go.sum | 8 +- util/confutil/config.go | 4 +- util/dockerutil/client.go | 3 +- vendor/github.com/docker/docker/api/common.go | 2 +- .../github.com/docker/docker/api/swagger.yaml | 876 +++--------------- .../docker/docker/api/types/client.go | 27 +- .../docker/api/types/container/container.go | 133 --- .../docker/api/types/container/health.go | 26 - .../api/types/container/network_settings.go | 56 -- .../docker/api/types/container/stats.go | 30 +- .../docker/docker/api/types/filters/errors.go | 13 + .../docker/docker/api/types/filters/parse.go | 16 +- .../driver_data.go => graph_driver_data.go} | 8 +- .../docker/api/types/image/image_inspect.go | 140 --- .../docker/docker/api/types/image/opts.go | 32 +- .../docker/docker/api/types/image/summary.go | 9 - .../docker/docker/api/types/mount/mount.go | 7 - .../docker/api/types/network/endpoint.go | 6 - .../docker/api/types/network/network.go | 4 +- .../docker/api/types/{container => }/port.go | 2 +- .../docker/api/types/registry/authconfig.go | 18 +- .../docker/api/types/registry/registry.go | 28 +- .../docker/api/types/registry/search.go | 9 +- .../docker/docker/api/types/system/info.go | 13 +- .../docker/docker/api/types/types.go | 324 ++++++- .../docker/api/types/types_deprecated.go | 243 +++-- .../docker/docker/client/build_prune.go | 17 +- .../docker/docker/client/checkpoint_create.go | 9 +- .../docker/docker/client/checkpoint_delete.go | 5 - .../github.com/docker/docker/client/client.go | 10 +- .../docker/docker/client/config_inspect.go | 5 +- .../docker/docker/client/config_remove.go | 4 - .../docker/docker/client/config_update.go | 4 - .../docker/docker/client/container_attach.go | 9 +- .../docker/docker/client/container_commit.go | 9 +- .../docker/docker/client/container_copy.go | 25 +- .../docker/docker/client/container_create.go | 52 +- .../docker/docker/client/container_diff.go | 11 +- .../docker/docker/client/container_exec.go | 17 +- .../docker/docker/client/container_export.go | 5 - .../docker/docker/client/container_inspect.go | 28 +- .../docker/docker/client/container_kill.go | 5 - .../docker/docker/client/container_list.go | 5 +- .../docker/docker/client/container_logs.go | 9 +- .../docker/docker/client/container_pause.go | 5 - .../docker/docker/client/container_prune.go | 11 +- .../docker/docker/client/container_remove.go | 5 - .../docker/docker/client/container_rename.go | 5 - .../docker/docker/client/container_resize.go | 13 +- .../docker/docker/client/container_restart.go | 5 - .../docker/docker/client/container_start.go | 5 - .../docker/docker/client/container_stats.go | 10 - .../docker/docker/client/container_stop.go | 5 - .../docker/docker/client/container_top.go | 9 +- .../docker/docker/client/container_unpause.go | 5 - .../docker/docker/client/container_update.go | 9 +- .../docker/docker/client/container_wait.go | 6 - .../github.com/docker/docker/client/errors.go | 12 +- .../github.com/docker/docker/client/hijack.go | 22 +- .../docker/docker/client/image_build.go | 118 +-- .../docker/docker/client/image_history.go | 21 +- .../docker/docker/client/image_import.go | 16 +- .../docker/docker/client/image_inspect.go | 103 +- .../docker/docker/client/image_load.go | 28 +- .../docker/docker/client/image_prune.go | 11 +- .../docker/docker/client/image_save.go | 15 +- .../{client_interfaces.go => interface.go} | 51 +- ...heckpoint.go => interface_experimental.go} | 10 +- .../docker/docker/client/interface_stable.go | 10 + .../docker/docker/client/network_connect.go | 10 - .../docker/client/network_disconnect.go | 10 - .../docker/docker/client/network_inspect.go | 5 +- .../docker/docker/client/network_prune.go | 11 +- .../docker/docker/client/network_remove.go | 4 - .../docker/docker/client/node_inspect.go | 5 +- .../docker/docker/client/node_remove.go | 5 - .../docker/docker/client/node_update.go | 5 - .../docker/docker/client/options.go | 5 +- .../docker/docker/client/plugin_disable.go | 4 - .../docker/docker/client/plugin_enable.go | 4 - .../docker/docker/client/plugin_inspect.go | 5 +- .../docker/docker/client/plugin_push.go | 4 - .../docker/docker/client/plugin_remove.go | 5 - .../docker/docker/client/plugin_set.go | 5 - .../docker/docker/client/plugin_upgrade.go | 7 +- .../docker/docker/client/request.go | 42 +- .../docker/docker/client/secret_inspect.go | 7 +- .../docker/docker/client/secret_remove.go | 4 - .../docker/docker/client/secret_update.go | 4 - .../docker/docker/client/service_inspect.go | 6 +- .../docker/docker/client/service_logs.go | 5 - .../docker/docker/client/service_remove.go | 5 - .../docker/docker/client/service_update.go | 12 +- .../docker/docker/client/task_inspect.go | 6 +- .../github.com/docker/docker/client/utils.go | 66 +- .../docker/docker/client/volume_inspect.go | 5 +- .../docker/docker/client/volume_prune.go | 11 +- .../docker/docker/client/volume_remove.go | 5 - .../docker/docker/client/volume_update.go | 4 - .../docker/docker/errdefs/helpers.go | 52 +- .../docker/docker/errdefs/http_helpers.go | 29 +- vendor/github.com/docker/docker/errdefs/is.go | 26 +- .../docker/internal/lazyregexp/lazyregexp.go | 90 -- .../docker/docker/pkg/archive/archive.go | 285 +++--- .../docker/pkg/archive/archive_linux.go | 11 +- .../docker/pkg/archive/archive_other.go | 2 +- .../docker/docker/pkg/archive/archive_unix.go | 5 +- .../docker/pkg/archive/archive_windows.go | 2 +- .../docker/docker/pkg/archive/changes.go | 16 +- .../docker/pkg/archive/changes_linux.go | 17 +- .../docker/pkg/archive/changes_other.go | 12 +- .../docker/docker/pkg/archive/changes_unix.go | 22 +- .../docker/pkg/archive/changes_windows.go | 9 +- .../docker/docker/pkg/archive/copy.go | 17 +- .../docker/docker/pkg/archive/copy_unix.go | 2 +- .../docker/docker/pkg/archive/copy_windows.go | 2 +- .../docker/docker/pkg/archive/dev_freebsd.go | 7 - .../docker/docker/pkg/archive/dev_unix.go | 9 - .../docker/docker/pkg/archive/diff.go | 11 +- .../docker/docker/pkg/archive/time.go | 38 - .../docker/docker/pkg/archive/time_linux.go | 16 + .../docker/pkg/archive/time_nonwindows.go | 40 - .../docker/pkg/archive/time_unsupported.go | 16 + .../docker/docker/pkg/archive/whiteouts.go | 2 +- .../docker/docker/pkg/archive/wrap.go | 2 +- .../docker/pkg/archive/xattr_supported.go | 52 -- .../pkg/archive/xattr_supported_linux.go | 5 - .../pkg/archive/xattr_supported_unix.go | 7 - .../docker/pkg/archive/xattr_unsupported.go | 11 - .../docker/docker/pkg/idtools/idtools.go | 82 +- .../docker/docker/pkg/idtools/idtools_unix.go | 180 +++- .../docker/pkg/idtools/idtools_windows.go | 12 +- .../docker/pkg/idtools/usergroupadd_linux.go | 166 ++++ .../pkg/idtools/usergroupadd_unsupported.go | 12 + .../docker/docker/pkg/idtools/utils_unix.go | 26 + .../docker/docker/pkg/ioutils/buffer.go | 51 + .../docker/docker/pkg/ioutils/bytespipe.go | 193 ++++ .../atomicwriter.go => ioutils/fswriters.go} | 32 +- .../pkg/ioutils/fswriters_deprecated.go | 44 - .../docker/docker/pkg/ioutils/readers.go | 66 +- .../docker/docker/pkg/ioutils/writeflusher.go | 6 +- .../docker/docker/pkg/ioutils/writers.go | 53 ++ .../docker/docker/pkg/pools/pools.go | 137 +++ .../docker/docker/pkg/stringid/stringid.go | 54 +- .../docker/docker/pkg/system/args_windows.go | 16 + .../docker/docker/pkg/system/chtimes.go | 48 + .../docker/pkg/system/chtimes_nowindows.go | 14 + .../chtimes_windows.go} | 19 +- .../docker/docker/pkg/system/errors.go | 6 + .../docker/docker/pkg/system/filesys.go | 19 + .../docker/docker/pkg/system/filesys_unix.go | 16 + .../docker/pkg/system/filesys_windows.go | 135 +++ .../docker/docker/pkg/system/init_windows.go | 16 + .../docker/docker/pkg/system/lstat_unix.go | 22 + .../docker/docker/pkg/system/lstat_windows.go | 16 + .../docker/docker/pkg/system/mknod.go | 18 + .../docker/docker/pkg/system/mknod_freebsd.go | 15 + .../docker/docker/pkg/system/mknod_unix.go | 15 + .../docker/docker/pkg/system/stat_bsd.go | 17 + .../docker/docker/pkg/system/stat_darwin.go | 15 + .../docker/docker/pkg/system/stat_illumos.go | 15 + .../docker/docker/pkg/system/stat_linux.go | 24 + .../docker/docker/pkg/system/stat_openbsd.go | 15 + .../docker/docker/pkg/system/stat_unix.go | 70 ++ .../docker/docker/pkg/system/stat_windows.go | 54 ++ .../docker/docker/pkg/system/utimes_unix.go | 24 + .../docker/pkg/system/utimes_unsupported.go | 10 + .../docker/docker/pkg/system/xattrs.go | 18 + .../docker/docker/pkg/system/xattrs_linux.go | 47 + .../docker/pkg/system/xattrs_unsupported.go | 13 + .../github.com/docker/docker/registry/auth.go | 33 +- .../docker/docker/registry/config.go | 114 ++- .../docker/docker/registry/registry.go | 21 +- .../docker/docker/registry/search_session.go | 33 +- .../docker/docker/registry/service.go | 26 +- .../docker/docker/registry/service_v2.go | 59 +- .../docker/docker/registry/types.go | 21 + vendor/modules.txt | 9 +- 182 files changed, 3094 insertions(+), 2915 deletions(-) delete mode 100644 vendor/github.com/docker/docker/api/types/container/health.go delete mode 100644 vendor/github.com/docker/docker/api/types/container/network_settings.go rename vendor/github.com/docker/docker/api/types/{storage/driver_data.go => graph_driver_data.go} (75%) delete mode 100644 vendor/github.com/docker/docker/api/types/image/image_inspect.go rename vendor/github.com/docker/docker/api/types/{container => }/port.go (96%) rename vendor/github.com/docker/docker/client/{client_interfaces.go => interface.go} (89%) rename vendor/github.com/docker/docker/client/{checkpoint.go => interface_experimental.go} (76%) create mode 100644 vendor/github.com/docker/docker/client/interface_stable.go delete mode 100644 vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/dev_unix.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/time.go create mode 100644 vendor/github.com/docker/docker/pkg/archive/time_linux.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go create mode 100644 vendor/github.com/docker/docker/pkg/archive/time_unsupported.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/xattr_supported.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go delete mode 100644 vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go create mode 100644 vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go create mode 100644 vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go create mode 100644 vendor/github.com/docker/docker/pkg/idtools/utils_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/buffer.go create mode 100644 vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go rename vendor/github.com/docker/docker/pkg/{atomicwriter/atomicwriter.go => ioutils/fswriters.go} (74%) delete mode 100644 vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go create mode 100644 vendor/github.com/docker/docker/pkg/pools/pools.go create mode 100644 vendor/github.com/docker/docker/pkg/system/args_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/system/chtimes.go create mode 100644 vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go rename vendor/github.com/docker/docker/pkg/{archive/time_windows.go => system/chtimes_windows.go} (50%) create mode 100644 vendor/github.com/docker/docker/pkg/system/errors.go create mode 100644 vendor/github.com/docker/docker/pkg/system/filesys.go create mode 100644 vendor/github.com/docker/docker/pkg/system/filesys_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/system/filesys_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/system/init_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/system/lstat_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/system/lstat_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/system/mknod.go create mode 100644 vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go create mode 100644 vendor/github.com/docker/docker/pkg/system/mknod_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_bsd.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_darwin.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_illumos.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_linux.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_openbsd.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/system/stat_windows.go create mode 100644 vendor/github.com/docker/docker/pkg/system/utimes_unix.go create mode 100644 vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go create mode 100644 vendor/github.com/docker/docker/pkg/system/xattrs.go create mode 100644 vendor/github.com/docker/docker/pkg/system/xattrs_linux.go create mode 100644 vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go diff --git a/build/build.go b/build/build.go index acec972d..a51e925a 100644 --- a/build/build.go +++ b/build/build.go @@ -835,7 +835,7 @@ func remoteDigestWithMoby(ctx context.Context, d *driver.DriverHandle, name stri if err != nil { return "", err } - img, err := api.ImageInspect(ctx, name) + img, _, err := api.ImageInspectWithRaw(ctx, name) if err != nil { return "", err } diff --git a/commands/build.go b/commands/build.go index ce89d11d..f0bd44b7 100644 --- a/commands/build.go +++ b/commands/build.go @@ -41,7 +41,7 @@ import ( "github.com/docker/cli/cli/command" dockeropts "github.com/docker/cli/opts" "github.com/docker/docker/api/types/versions" - "github.com/docker/docker/pkg/atomicwriter" + "github.com/docker/docker/pkg/ioutils" "github.com/moby/buildkit/client" "github.com/moby/buildkit/exporter/containerimage/exptypes" "github.com/moby/buildkit/frontend/subrequests" @@ -745,7 +745,7 @@ func writeMetadataFile(filename string, dt interface{}) error { if err != nil { return err } - return atomicwriter.WriteFile(filename, b, 0644) + return ioutils.AtomicWriteFile(filename, b, 0644) } func decodeExporterResponse(exporterResponse map[string]string) map[string]interface{} { diff --git a/driver/docker-container/driver.go b/driver/docker-container/driver.go index f34c3795..2fc9577d 100644 --- a/driver/docker-container/driver.go +++ b/driver/docker-container/driver.go @@ -105,9 +105,8 @@ func (d *Driver) create(ctx context.Context, l progress.SubLogger) error { }); err != nil { // image pulling failed, check if it exists in local image store. // if not, return pulling error. otherwise log it. - _, errInspect := d.DockerAPI.ImageInspect(ctx, imageName) - found := errInspect == nil - if !found { + _, _, errInspect := d.DockerAPI.ImageInspectWithRaw(ctx, imageName) + if errInspect != nil { return err } l.Wrap("pulling failed, using local image "+imageName, func() error { return nil }) diff --git a/go.mod b/go.mod index efc66164..19f605f5 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/distribution/reference v0.6.0 github.com/docker/cli v27.5.1+incompatible github.com/docker/cli-docs-tool v0.9.0 - github.com/docker/docker v28.0.0-rc.1+incompatible + github.com/docker/docker v27.5.1+incompatible github.com/docker/go-units v0.5.0 github.com/gofrs/flock v0.12.1 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 @@ -173,7 +173,7 @@ require ( golang.org/x/oauth2 v0.23.0 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.27.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect diff --git a/go.sum b/go.sum index 557bc725..ddce6653 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/docker/cli-docs-tool v0.9.0/go.mod h1:ClrwlNW+UioiRyH9GiAOe1o3J/TsY3T 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 v28.0.0-rc.1+incompatible h1:xUbdsVxJIFvyZ+958MzyyIT7VuHO4Ecao9hKhl7kGUc= -github.com/docker/docker v28.0.0-rc.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.5.1+incompatible h1:4PYU5dnBYqRQi0294d1FBECqT9ECWeQAIfE8q4YnPY8= +github.com/docker/docker v27.5.1+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= @@ -572,8 +572,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 h1:2oV8dfuIkM1Ti7DwXc0BJfnwr9csz4TDXI9EmiI+Rbw= -google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 h1:T6rh4haD3GVYsgEfWExoCZA2o2FmbNyKpTuAxbEFPTg= +google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9/go.mod h1:wp2WsuBYj6j8wUdo3ToZsdxxixbvQNAHqVJrTgi5E5M= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= google.golang.org/grpc v1.0.5/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= diff --git a/util/confutil/config.go b/util/confutil/config.go index a0e26de2..ebd42b2a 100644 --- a/util/confutil/config.go +++ b/util/confutil/config.go @@ -8,7 +8,7 @@ import ( "sync" "github.com/docker/cli/cli/command" - "github.com/docker/docker/pkg/atomicwriter" + "github.com/docker/docker/pkg/ioutils" "github.com/moby/buildkit/cmd/buildkitd/config" "github.com/pelletier/go-toml" "github.com/pkg/errors" @@ -106,7 +106,7 @@ func (c *Config) MkdirAll(dir string, perm os.FileMode) error { // AtomicWriteFile writes data to a file within the config dir atomically func (c *Config) AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { f := filepath.Join(c.dir, filename) - if err := atomicwriter.WriteFile(f, data, perm); err != nil { + if err := ioutils.AtomicWriteFile(f, data, perm); err != nil { return err } if c.chowner == nil { diff --git a/util/dockerutil/client.go b/util/dockerutil/client.go index 39318773..c5ec65b2 100644 --- a/util/dockerutil/client.go +++ b/util/dockerutil/client.go @@ -7,7 +7,6 @@ import ( "github.com/docker/buildx/util/progress" "github.com/docker/cli/cli/command" - "github.com/docker/docker/api/types/image" dockerclient "github.com/docker/docker/client" ) @@ -53,7 +52,7 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri w.mu.Unlock() } - resp, err := dapi.ImageLoad(ctx, pr, image.LoadOptions{}) + resp, err := dapi.ImageLoad(ctx, pr, false) defer close(done) if err != nil { handleErr(err) diff --git a/vendor/github.com/docker/docker/api/common.go b/vendor/github.com/docker/docker/api/common.go index 2c62cd40..93d64cd8 100644 --- a/vendor/github.com/docker/docker/api/common.go +++ b/vendor/github.com/docker/docker/api/common.go @@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api" // Common constants for daemon and client. const ( // DefaultVersion of the current REST API. - DefaultVersion = "1.48" + DefaultVersion = "1.47" // MinSupportedAPIVersion is the minimum API version that can be supported // by the API server, specified as "major.minor". Note that the daemon diff --git a/vendor/github.com/docker/docker/api/swagger.yaml b/vendor/github.com/docker/docker/api/swagger.yaml index 21cdf288..142bb038 100644 --- a/vendor/github.com/docker/docker/api/swagger.yaml +++ b/vendor/github.com/docker/docker/api/swagger.yaml @@ -19,10 +19,10 @@ produces: consumes: - "application/json" - "text/plain" -basePath: "/v1.48" +basePath: "/v1.47" info: title: "Docker Engine API" - version: "1.48" + version: "1.47" x-logo: url: "https://docs.docker.com/assets/images/logo-docker-main.png" description: | @@ -55,14 +55,14 @@ info: the URL is not supported by the daemon, a HTTP `400 Bad Request` error message is returned. - If you omit the version-prefix, the current version of the API (v1.48) is used. - For example, calling `/info` is the same as calling `/v1.48/info`. Using the + If you omit the version-prefix, the current version of the API (v1.47) is used. + For example, calling `/info` is the same as calling `/v1.47/info`. Using the API without a version-prefix is deprecated and will be removed in a future release. Engine releases in the near future should support this version of the API, so your client will continue to work even if it is talking to a newer Engine. - The API uses an open schema model, which means the server may add extra properties + The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer @@ -212,7 +212,6 @@ definitions: - `bind` a mount of a file or directory from the host into the container. - `volume` a docker volume with the given `Name`. - - `image` a docker image - `tmpfs` a `tmpfs`. - `npipe` a named pipe from the host into the container. - `cluster` a Swarm cluster volume @@ -220,7 +219,6 @@ definitions: enum: - "bind" - "volume" - - "image" - "tmpfs" - "npipe" - "cluster" @@ -352,7 +350,6 @@ definitions: - `bind` Mounts a file or directory from the host into the container. Must exist prior to creating the container. - `volume` Creates a volume with the given name and options (or uses a pre-existing volume with the same name and options). These are **not** removed when the container is removed. - - `image` Mounts an image. - `tmpfs` Create a tmpfs with the given options. The mount source cannot be specified for tmpfs. - `npipe` Mounts a named pipe from the host into the container. Must exist prior to creating the container. - `cluster` a Swarm cluster volume @@ -360,7 +357,6 @@ definitions: enum: - "bind" - "volume" - - "image" - "tmpfs" - "npipe" - "cluster" @@ -435,14 +431,6 @@ definitions: description: "Source path inside the volume. Must be relative without any back traversals." type: "string" example: "dir-inside-volume/subdirectory" - ImageOptions: - description: "Optional configuration for the `image` type." - type: "object" - properties: - Subpath: - description: "Source path inside the image. Must be relative without any back traversals." - type: "string" - example: "dir-inside-image/subdirectory" TmpfsOptions: description: "Optional configuration for the `tmpfs` type." type: "object" @@ -1930,7 +1918,7 @@ definitions: type: "string" example: "4443" - DriverData: + GraphDriverData: description: | Information about the storage driver used to store the container's and image's filesystem. @@ -2004,33 +1992,6 @@ definitions: type: "string" x-nullable: false example: "sha256:ec3f0931a6e6b6855d76b2d7b0be30e81860baccd891b2e243280bf1cd8ad710" - Descriptor: - description: | - Descriptor is an OCI descriptor of the image target. - In case of a multi-platform image, this descriptor points to the OCI index - or a manifest list. - - This field is only present if the daemon provides a multi-platform image store. - - WARNING: This is experimental and may change at any time without any backward - compatibility. - x-nullable: true - $ref: "#/definitions/OCIDescriptor" - Manifests: - description: | - Manifests is a list of image manifests available in this image. It - provides a more detailed view of the platform-specific image manifests or - other image-attached data like build attestations. - - Only available if the daemon provides a multi-platform image store - and the `manifests` option is set in the inspect request. - - WARNING: This is experimental and may change at any time without any backward - compatibility. - type: "array" - x-nullable: true - items: - $ref: "#/definitions/ImageManifestSummary" RepoTags: description: | List of image names/tags in the local image cache that reference this @@ -2147,7 +2108,7 @@ definitions: format: "int64" example: 1239828 GraphDriver: - $ref: "#/definitions/DriverData" + $ref: "#/definitions/GraphDriverData" RootFS: description: | Information about the image's RootFS, including the layer IDs. @@ -2318,18 +2279,6 @@ definitions: x-omitempty: true items: $ref: "#/definitions/ImageManifestSummary" - Descriptor: - description: | - Descriptor is an OCI descriptor of the image target. - In case of a multi-platform image, this descriptor points to the OCI index - or a manifest list. - - This field is only present if the daemon provides a multi-platform image store. - - WARNING: This is experimental and may change at any time without any backward - compatibility. - x-nullable: true - $ref: "#/definitions/OCIDescriptor" AuthConfig: type: "object" @@ -2549,11 +2498,6 @@ definitions: `overlay`). type: "string" example: "overlay" - EnableIPv4: - description: | - Whether the network was created with IPv4 enabled. - type: "boolean" - example: true EnableIPv6: description: | Whether the network was created with IPv6 enabled. @@ -2955,16 +2899,6 @@ definitions: example: com.example.some-label: "some-value" com.example.some-other-label: "some-other-value" - GwPriority: - description: | - This property determines which endpoint will provide the default - gateway for a container. The endpoint with the highest priority will - be used. If multiple endpoints have the same priority, endpoints are - lexicographically sorted based on their network name, and the one - that sorts first is picked. - type: "number" - example: - - 10 # Operational data NetworkID: @@ -5326,551 +5260,6 @@ definitions: type: "string" example: [] - ContainerStatsResponse: - description: | - Statistics sample for a container. - type: "object" - x-go-name: "StatsResponse" - title: "ContainerStatsResponse" - properties: - name: - description: "Name of the container" - type: "string" - x-nullable: true - example: "boring_wozniak" - id: - description: "ID of the container" - type: "string" - x-nullable: true - example: "ede54ee1afda366ab42f824e8a5ffd195155d853ceaec74a927f249ea270c743" - read: - description: | - Date and time at which this sample was collected. - The value is formatted as [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) - with nano-seconds. - type: "string" - format: "date-time" - example: "2025-01-16T13:55:22.165243637Z" - preread: - description: | - Date and time at which this first sample was collected. This field - is not propagated if the "one-shot" option is set. If the "one-shot" - option is set, this field may be omitted, empty, or set to a default - date (`0001-01-01T00:00:00Z`). - - The value is formatted as [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) - with nano-seconds. - type: "string" - format: "date-time" - example: "2025-01-16T13:55:21.160452595Z" - pids_stats: - $ref: "#/definitions/ContainerPidsStats" - blkio_stats: - $ref: "#/definitions/ContainerBlkioStats" - num_procs: - description: | - The number of processors on the system. - - This field is Windows-specific and always zero for Linux containers. - type: "integer" - format: "uint32" - example: 16 - storage_stats: - $ref: "#/definitions/ContainerStorageStats" - cpu_stats: - $ref: "#/definitions/ContainerCPUStats" - precpu_stats: - $ref: "#/definitions/ContainerCPUStats" - memory_stats: - $ref: "#/definitions/ContainerMemoryStats" - networks: - description: | - Network statistics for the container per interface. - - This field is omitted if the container has no networking enabled. - x-nullable: true - additionalProperties: - $ref: "#/definitions/ContainerNetworkStats" - example: - eth0: - rx_bytes: 5338 - rx_dropped: 0 - rx_errors: 0 - rx_packets: 36 - tx_bytes: 648 - tx_dropped: 0 - tx_errors: 0 - tx_packets: 8 - eth5: - rx_bytes: 4641 - rx_dropped: 0 - rx_errors: 0 - rx_packets: 26 - tx_bytes: 690 - tx_dropped: 0 - tx_errors: 0 - tx_packets: 9 - - ContainerBlkioStats: - description: | - BlkioStats stores all IO service stats for data read and write. - - This type is Linux-specific and holds many fields that are specific to cgroups v1. - On a cgroup v2 host, all fields other than `io_service_bytes_recursive` - are omitted or `null`. - - This type is only populated on Linux and omitted for Windows containers. - type: "object" - x-go-name: "BlkioStats" - x-nullable: true - properties: - io_service_bytes_recursive: - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_serviced_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_queue_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_service_time_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_wait_time_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_merged_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - io_time_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - sectors_recursive: - description: | - This field is only available when using Linux containers with - cgroups v1. It is omitted or `null` when using cgroups v2. - x-nullable: true - type: "array" - items: - $ref: "#/definitions/ContainerBlkioStatEntry" - example: - io_service_bytes_recursive: [ - {"major": 254, "minor": 0, "op": "read", "value": 7593984}, - {"major": 254, "minor": 0, "op": "write", "value": 100} - ] - io_serviced_recursive: null - io_queue_recursive: null - io_service_time_recursive: null - io_wait_time_recursive: null - io_merged_recursive: null - io_time_recursive: null - sectors_recursive: null - - ContainerBlkioStatEntry: - description: | - Blkio stats entry. - - This type is Linux-specific and omitted for Windows containers. - type: "object" - x-go-name: "BlkioStatEntry" - x-nullable: true - properties: - major: - type: "integer" - format: "uint64" - example: 254 - minor: - type: "integer" - format: "uint64" - example: 0 - op: - type: "string" - example: "read" - value: - type: "integer" - format: "uint64" - example: 7593984 - - ContainerCPUStats: - description: | - CPU related info of the container - type: "object" - x-go-name: "CPUStats" - x-nullable: true - properties: - cpu_usage: - $ref: "#/definitions/ContainerCPUUsage" - system_cpu_usage: - description: | - System Usage. - - This field is Linux-specific and omitted for Windows containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 5 - online_cpus: - description: | - Number of online CPUs. - - This field is Linux-specific and omitted for Windows containers. - type: "integer" - format: "uint32" - x-nullable: true - example: 5 - throttling_data: - $ref: "#/definitions/ContainerThrottlingData" - - ContainerCPUUsage: - description: | - All CPU stats aggregated since container inception. - type: "object" - x-go-name: "CPUUsage" - x-nullable: true - properties: - total_usage: - description: | - Total CPU time consumed in nanoseconds (Linux) or 100's of nanoseconds (Windows). - type: "integer" - format: "uint64" - example: 29912000 - percpu_usage: - description: | - Total CPU time (in nanoseconds) consumed per core (Linux). - - This field is Linux-specific when using cgroups v1. It is omitted - when using cgroups v2 and Windows containers. - type: "array" - x-nullable: true - items: - type: "integer" - format: "uint64" - example: 29912000 - - usage_in_kernelmode: - description: | - Time (in nanoseconds) spent by tasks of the cgroup in kernel mode (Linux), - or time spent (in 100's of nanoseconds) by all container processes in - kernel mode (Windows). - - Not populated for Windows containers using Hyper-V isolation. - type: "integer" - format: "uint64" - example: 21994000 - usage_in_usermode: - description: | - Time (in nanoseconds) spent by tasks of the cgroup in user mode (Linux), - or time spent (in 100's of nanoseconds) by all container processes in - kernel mode (Windows). - - Not populated for Windows containers using Hyper-V isolation. - type: "integer" - format: "uint64" - example: 7918000 - - ContainerPidsStats: - description: | - PidsStats contains Linux-specific stats of a container's process-IDs (PIDs). - - This type is Linux-specific and omitted for Windows containers. - type: "object" - x-go-name: "PidsStats" - x-nullable: true - properties: - current: - description: | - Current is the number of PIDs in the cgroup. - type: "integer" - format: "uint64" - x-nullable: true - example: 5 - limit: - description: | - Limit is the hard limit on the number of pids in the cgroup. - A "Limit" of 0 means that there is no limit. - type: "integer" - format: "uint64" - x-nullable: true - example: 18446744073709551615 - - ContainerThrottlingData: - description: | - CPU throttling stats of the container. - - This type is Linux-specific and omitted for Windows containers. - type: "object" - x-go-name: "ThrottlingData" - x-nullable: true - properties: - periods: - description: | - Number of periods with throttling active. - type: "integer" - format: "uint64" - example: 0 - throttled_periods: - description: | - Number of periods when the container hit its throttling limit. - type: "integer" - format: "uint64" - example: 0 - throttled_time: - description: | - Aggregated time (in nanoseconds) the container was throttled for. - type: "integer" - format: "uint64" - example: 0 - - ContainerMemoryStats: - description: | - Aggregates all memory stats since container inception on Linux. - Windows returns stats for commit and private working set only. - type: "object" - x-go-name: "MemoryStats" - properties: - usage: - description: | - Current `res_counter` usage for memory. - - This field is Linux-specific and omitted for Windows containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - max_usage: - description: | - Maximum usage ever recorded. - - This field is Linux-specific and only supported on cgroups v1. - It is omitted when using cgroups v2 and for Windows containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - stats: - description: | - All the stats exported via memory.stat. when using cgroups v2. - - This field is Linux-specific and omitted for Windows containers. - type: "object" - additionalProperties: - type: "integer" - format: "uint64" - x-nullable: true - example: - { - "active_anon": 1572864, - "active_file": 5115904, - "anon": 1572864, - "anon_thp": 0, - "file": 7626752, - "file_dirty": 0, - "file_mapped": 2723840, - "file_writeback": 0, - "inactive_anon": 0, - "inactive_file": 2510848, - "kernel_stack": 16384, - "pgactivate": 0, - "pgdeactivate": 0, - "pgfault": 2042, - "pglazyfree": 0, - "pglazyfreed": 0, - "pgmajfault": 45, - "pgrefill": 0, - "pgscan": 0, - "pgsteal": 0, - "shmem": 0, - "slab": 1180928, - "slab_reclaimable": 725576, - "slab_unreclaimable": 455352, - "sock": 0, - "thp_collapse_alloc": 0, - "thp_fault_alloc": 1, - "unevictable": 0, - "workingset_activate": 0, - "workingset_nodereclaim": 0, - "workingset_refault": 0 - } - failcnt: - description: | - Number of times memory usage hits limits. - - This field is Linux-specific and only supported on cgroups v1. - It is omitted when using cgroups v2 and for Windows containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - limit: - description: | - This field is Linux-specific and omitted for Windows containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 8217579520 - commitbytes: - description: | - Committed bytes. - - This field is Windows-specific and omitted for Linux containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - commitpeakbytes: - description: | - Peak committed bytes. - - This field is Windows-specific and omitted for Linux containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - privateworkingset: - description: | - Private working set. - - This field is Windows-specific and omitted for Linux containers. - type: "integer" - format: "uint64" - x-nullable: true - example: 0 - - ContainerNetworkStats: - description: | - Aggregates the network stats of one container - type: "object" - x-go-name: "NetworkStats" - x-nullable: true - properties: - rx_bytes: - description: | - Bytes received. Windows and Linux. - type: "integer" - format: "uint64" - example: 5338 - rx_packets: - description: | - Packets received. Windows and Linux. - type: "integer" - format: "uint64" - example: 36 - rx_errors: - description: | - Received errors. Not used on Windows. - - This field is Linux-specific and always zero for Windows containers. - type: "integer" - format: "uint64" - example: 0 - rx_dropped: - description: | - Incoming packets dropped. Windows and Linux. - type: "integer" - format: "uint64" - example: 0 - tx_bytes: - description: | - Bytes sent. Windows and Linux. - type: "integer" - format: "uint64" - example: 1200 - tx_packets: - description: | - Packets sent. Windows and Linux. - type: "integer" - format: "uint64" - example: 12 - tx_errors: - description: | - Sent errors. Not used on Windows. - - This field is Linux-specific and always zero for Windows containers. - type: "integer" - format: "uint64" - example: 0 - tx_dropped: - description: | - Outgoing packets dropped. Windows and Linux. - type: "integer" - format: "uint64" - example: 0 - endpoint_id: - description: | - Endpoint ID. Not used on Linux. - - This field is Windows-specific and omitted for Linux containers. - type: "string" - x-nullable: true - instance_id: - description: | - Instance ID. Not used on Linux. - - This field is Windows-specific and omitted for Linux containers. - type: "string" - x-nullable: true - - ContainerStorageStats: - description: | - StorageStats is the disk I/O stats for read/write on Windows. - - This type is Windows-specific and omitted for Linux containers. - type: "object" - x-go-name: "StorageStats" - x-nullable: true - properties: - read_count_normalized: - type: "integer" - format: "uint64" - x-nullable: true - example: 7593984 - read_size_bytes: - type: "integer" - format: "uint64" - x-nullable: true - example: 7593984 - write_count_normalized: - type: "integer" - format: "uint64" - x-nullable: true - example: 7593984 - write_size_bytes: - type: "integer" - format: "uint64" - x-nullable: true - example: 7593984 - ContainerWaitResponse: description: "OK response to ContainerWait operation" type: "object" @@ -6120,28 +5509,13 @@ definitions: type: "boolean" example: true BridgeNfIptables: - description: | - Indicates if `bridge-nf-call-iptables` is available on the host when - the daemon was started. - -


- - > **Deprecated**: netfilter module is now loaded on-demand and no longer - > during daemon startup, making this field obsolete. This field is always - > `false` and will be removed in a API v1.49. + description: "Indicates if `bridge-nf-call-iptables` is available on the host." type: "boolean" - example: false + example: true BridgeNfIp6tables: - description: | - Indicates if `bridge-nf-call-ip6tables` is available on the host. - -


- - > **Deprecated**: netfilter module is now loaded on-demand, and no longer - > during daemon startup, making this field obsolete. This field is always - > `false` and will be removed in a API v1.49. + description: "Indicates if `bridge-nf-call-ip6tables` is available on the host." type: "boolean" - example: false + example: true Debug: description: | Indicates if the daemon is running in debug-mode / with debug-level @@ -6571,27 +5945,55 @@ definitions: List of IP ranges to which nondistributable artifacts can be pushed, using the CIDR syntax [RFC 4632](https://tools.ietf.org/html/4632). -


+ Some images (for example, Windows base images) contain artifacts + whose distribution is restricted by license. When these images are + pushed to a registry, restricted artifacts are not included. + + This configuration override this behavior, and enables the daemon to + push nondistributable artifacts to all registries whose resolved IP + address is within the subnet described by the CIDR syntax. + + This option is useful when pushing images containing + nondistributable artifacts to a registry on an air-gapped network so + hosts on that network can pull the images without connecting to + another server. + + > **Warning**: Nondistributable artifacts typically have restrictions + > on how and where they can be distributed and shared. Only use this + > feature to push artifacts to private registries and ensure that you + > are in compliance with any terms that cover redistributing + > nondistributable artifacts. - > **Deprecated**: Pushing nondistributable artifacts is now always enabled - > and this field is always `null`. This field will be removed in a API v1.49. type: "array" items: type: "string" - example: [] + example: ["::1/128", "127.0.0.0/8"] AllowNondistributableArtifactsHostnames: description: | List of registry hostnames to which nondistributable artifacts can be pushed, using the format `[:]` or `[:]`. -


+ Some images (for example, Windows base images) contain artifacts + whose distribution is restricted by license. When these images are + pushed to a registry, restricted artifacts are not included. - > **Deprecated**: Pushing nondistributable artifacts is now always enabled - > and this field is always `null`. This field will be removed in a API v1.49. + This configuration override this behavior for the specified + registries. + + This option is useful when pushing images containing + nondistributable artifacts to a registry on an air-gapped network so + hosts on that network can pull the images without connecting to + another server. + + > **Warning**: Nondistributable artifacts typically have restrictions + > on how and where they can be distributed and shared. Only use this + > feature to push artifacts to private registries and ensure that you + > are in compliance with any terms that cover redistributing + > nondistributable artifacts. type: "array" items: type: "string" - example: [] + example: ["registry.internal.corp.example.com:3000", "[2001:db8:a0b:12f0::1]:443"] InsecureRegistryCIDRs: description: | List of IP ranges of insecure registries, using the CIDR syntax @@ -6599,7 +6001,7 @@ definitions: accept un-encrypted (HTTP) and/or untrusted (HTTPS with certificates from unknown CAs) communication. - By default, local registries (`::1/128` and `127.0.0.0/8`) are configured as + By default, local registries (`127.0.0.0/8`) are configured as insecure. All other registries are secure. Communicating with an insecure registry is not possible if the daemon assumes that registry is secure. @@ -6764,8 +6166,6 @@ definitions: Expected: description: | Commit ID of external tool expected by dockerd as set at build time. - - **Deprecated**: This field is deprecated and will be omitted in a API v1.49. type: "string" example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4" @@ -7836,14 +7236,6 @@ paths: type: "string" Platform: type: "string" - ImageManifestDescriptor: - $ref: "#/definitions/OCIDescriptor" - description: | - OCI descriptor of the platform-specific manifest of the image - the container was created from. - - Note: Only available if the daemon provides a multi-platform - image store. MountLabel: type: "string" ProcessLabel: @@ -7859,7 +7251,7 @@ paths: HostConfig: $ref: "#/definitions/HostConfig" GraphDriver: - $ref: "#/definitions/DriverData" + $ref: "#/definitions/GraphDriverData" SizeRw: description: | The size of files that have been created or changed by this @@ -8329,7 +7721,99 @@ paths: 200: description: "no error" schema: - $ref: "#/definitions/ContainerStatsResponse" + type: "object" + examples: + application/json: + read: "2015-01-08T22:57:31.547920715Z" + pids_stats: + current: 3 + networks: + eth0: + rx_bytes: 5338 + rx_dropped: 0 + rx_errors: 0 + rx_packets: 36 + tx_bytes: 648 + tx_dropped: 0 + tx_errors: 0 + tx_packets: 8 + eth5: + rx_bytes: 4641 + rx_dropped: 0 + rx_errors: 0 + rx_packets: 26 + tx_bytes: 690 + tx_dropped: 0 + tx_errors: 0 + tx_packets: 9 + memory_stats: + stats: + total_pgmajfault: 0 + cache: 0 + mapped_file: 0 + total_inactive_file: 0 + pgpgout: 414 + rss: 6537216 + total_mapped_file: 0 + writeback: 0 + unevictable: 0 + pgpgin: 477 + total_unevictable: 0 + pgmajfault: 0 + total_rss: 6537216 + total_rss_huge: 6291456 + total_writeback: 0 + total_inactive_anon: 0 + rss_huge: 6291456 + hierarchical_memory_limit: 67108864 + total_pgfault: 964 + total_active_file: 0 + active_anon: 6537216 + total_active_anon: 6537216 + total_pgpgout: 414 + total_cache: 0 + inactive_anon: 0 + active_file: 0 + pgfault: 964 + inactive_file: 0 + total_pgpgin: 477 + max_usage: 6651904 + usage: 6537216 + failcnt: 0 + limit: 67108864 + blkio_stats: {} + cpu_stats: + cpu_usage: + percpu_usage: + - 8646879 + - 24472255 + - 36438778 + - 30657443 + usage_in_usermode: 50000000 + total_usage: 100215355 + usage_in_kernelmode: 30000000 + system_cpu_usage: 739306590000000 + online_cpus: 4 + throttling_data: + periods: 0 + throttled_periods: 0 + throttled_time: 0 + precpu_stats: + cpu_usage: + percpu_usage: + - 8646879 + - 24350896 + - 36438778 + - 30657443 + usage_in_usermode: 50000000 + total_usage: 100093996 + usage_in_kernelmode: 30000000 + system_cpu_usage: 9492140000000 + online_cpus: 4 + throttling_data: + periods: 0 + throttled_periods: 0 + throttled_time: 0 404: description: "no such container" schema: @@ -9474,29 +8958,10 @@ paths: operationId: "BuildPrune" parameters: - name: "keep-storage" - in: "query" - description: | - Amount of disk space in bytes to keep for cache - - > **Deprecated**: This parameter is deprecated and has been renamed to "reserved-space". - > It is kept for backward compatibility and will be removed in API v1.49. - type: "integer" - format: "int64" - - name: "reserved-space" in: "query" description: "Amount of disk space in bytes to keep for cache" type: "integer" format: "int64" - - name: "max-used-space" - in: "query" - description: "Maximum amount of disk space allowed to keep for cache" - type: "integer" - format: "int64" - - name: "min-free-space" - in: "query" - description: "Target amount of free disk space after pruning" - type: "integer" - format: "int64" - name: "all" in: "query" type: "boolean" @@ -9563,13 +9028,7 @@ paths: parameters: - name: "fromImage" in: "query" - description: | - Name of the image to pull. If the name includes a tag or digest, specific behavior applies: - - - If only `fromImage` includes a tag, that tag is used. - - If both `fromImage` and `tag` are provided, `tag` takes precedence. - - If `fromImage` includes a digest, the image is pulled by digest, and `tag` is ignored. - - If neither a tag nor digest is specified, all tags are pulled. + description: "Name of the image to pull. The name may include a tag or digest. This parameter may only be used when pulling an image. The pull is cancelled if the HTTP connection is closed." type: "string" - name: "fromSrc" in: "query" @@ -9663,12 +9122,6 @@ paths: description: "Image name or id" type: "string" required: true - - name: "manifests" - in: "query" - description: "Include Manifests in the image summary." - type: "boolean" - default: false - required: false tags: ["Image"] /images/{name}/history: get: @@ -9747,20 +9200,6 @@ paths: description: "Image name or ID" type: "string" required: true - - name: "platform" - type: "string" - in: "query" - description: | - JSON-encoded OCI platform to select the platform-variant. - If omitted, it defaults to any locally available platform, - prioritizing the daemon's host platform. - - If the daemon provides a multi-platform image store, this selects - the platform-variant to show the history for. If the image is - a single-platform image, or if the multi-platform image does not - provide a variant matching the given platform, an error is returned. - - Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` tags: ["Image"] /images/{name}/push: post: @@ -10514,16 +9953,7 @@ paths: description: "Image name or ID" type: "string" required: true - - name: "platform" - type: "string" - in: "query" - description: | - JSON encoded OCI platform describing a platform which will be used - to select a platform-specific image to be saved if the image is - multi-platform. - If not provided, the full multi-platform image will be saved. - - Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` + tags: ["Image"] /images/get: get: summary: "Export several images" @@ -10590,16 +10020,6 @@ paths: description: "Suppress progress details during load." type: "boolean" default: false - - name: "platform" - type: "string" - in: "query" - description: | - JSON encoded OCI platform describing a platform which will be used - to select a platform-specific image to be load if the image is - multi-platform. - If not provided, the full multi-platform image will be loaded. - - Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}` tags: ["Image"] /containers/{id}/exec: post: @@ -11113,7 +10533,6 @@ paths: Created: "2016-10-19T06:21:00.416543526Z" Scope: "local" Driver: "bridge" - EnableIPv4: true EnableIPv6: false Internal: false Attachable: false @@ -11135,7 +10554,6 @@ paths: Created: "0001-01-01T00:00:00Z" Scope: "local" Driver: "null" - EnableIPv4: false EnableIPv6: false Internal: false Attachable: false @@ -11150,7 +10568,6 @@ paths: Created: "0001-01-01T00:00:00Z" Scope: "local" Driver: "host" - EnableIPv4: false EnableIPv6: false Internal: false Attachable: false @@ -11336,10 +10753,6 @@ paths: IPAM: description: "Optional custom IP scheme for the network." $ref: "#/definitions/IPAM" - EnableIPv4: - description: "Enable IPv4 on the network." - type: "boolean" - example: true EnableIPv6: description: "Enable IPv6 on the network." type: "boolean" @@ -11417,7 +10830,6 @@ paths: IPv4Address: "172.24.56.89" IPv6Address: "2001:db8::5689" MacAddress: "02:42:ac:12:05:02" - Priority: 100 tags: ["Network"] /networks/{id}/disconnect: diff --git a/vendor/github.com/docker/docker/api/types/client.go b/vendor/github.com/docker/docker/api/types/client.go index dce8260f..df791f02 100644 --- a/vendor/github.com/docker/docker/api/types/client.go +++ b/vendor/github.com/docker/docker/api/types/client.go @@ -11,7 +11,7 @@ import ( "github.com/docker/docker/api/types/registry" ) -// NewHijackedResponse initializes a [HijackedResponse] type. +// NewHijackedResponse intializes a HijackedResponse type func NewHijackedResponse(conn net.Conn, mediaType string) HijackedResponse { return HijackedResponse{Conn: conn, Reader: bufio.NewReader(conn), mediaType: mediaType} } @@ -129,6 +129,14 @@ type ImageBuildResponse struct { OSType string } +// RequestPrivilegeFunc is a function interface that +// clients can supply to retry operations after +// getting an authorization error. +// This function returns the registry authentication +// header value in base 64 format, or an error +// if the privilege request fails. +type RequestPrivilegeFunc func(context.Context) (string, error) + // NodeListOptions holds parameters to list nodes with. type NodeListOptions struct { Filters filters.Args @@ -227,18 +235,11 @@ type PluginDisableOptions struct { // PluginInstallOptions holds parameters to install a plugin. type PluginInstallOptions struct { - Disabled bool - AcceptAllPermissions bool - RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry - RemoteRef string // RemoteRef is the plugin name on the registry - - // PrivilegeFunc is a function that clients can supply to retry operations - // after getting an authorization error. This function returns the registry - // authentication header value in base64 encoded format, or an error if the - // privilege request fails. - // - // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. - PrivilegeFunc func(context.Context) (string, error) + Disabled bool + AcceptAllPermissions bool + RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry + RemoteRef string // RemoteRef is the plugin name on the registry + PrivilegeFunc RequestPrivilegeFunc AcceptPermissionsFunc func(context.Context, PluginPrivileges) (bool, error) Args []string } diff --git a/vendor/github.com/docker/docker/api/types/container/container.go b/vendor/github.com/docker/docker/api/types/container/container.go index 0244a354..711af12c 100644 --- a/vendor/github.com/docker/docker/api/types/container/container.go +++ b/vendor/github.com/docker/docker/api/types/container/container.go @@ -4,10 +4,6 @@ import ( "io" "os" "time" - - "github.com/docker/docker/api/types/mount" - "github.com/docker/docker/api/types/storage" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) // PruneReport contains the response for Engine API: @@ -46,132 +42,3 @@ type StatsResponseReader struct { Body io.ReadCloser `json:"body"` OSType string `json:"ostype"` } - -// MountPoint represents a mount point configuration inside the container. -// This is used for reporting the mountpoints in use by a container. -type MountPoint struct { - // Type is the type of mount, see `Type` definitions in - // github.com/docker/docker/api/types/mount.Type - Type mount.Type `json:",omitempty"` - - // Name is the name reference to the underlying data defined by `Source` - // e.g., the volume name. - Name string `json:",omitempty"` - - // Source is the source location of the mount. - // - // For volumes, this contains the storage location of the volume (within - // `/var/lib/docker/volumes/`). For bind-mounts, and `npipe`, this contains - // the source (host) part of the bind-mount. For `tmpfs` mount points, this - // field is empty. - Source string - - // Destination is the path relative to the container root (`/`) where the - // Source is mounted inside the container. - Destination string - - // Driver is the volume driver used to create the volume (if it is a volume). - Driver string `json:",omitempty"` - - // Mode is a comma separated list of options supplied by the user when - // creating the bind/volume mount. - // - // The default is platform-specific (`"z"` on Linux, empty on Windows). - Mode string - - // RW indicates whether the mount is mounted writable (read-write). - RW bool - - // Propagation describes how mounts are propagated from the host into the - // mount point, and vice-versa. Refer to the Linux kernel documentation - // for details: - // https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt - // - // This field is not used on Windows. - Propagation mount.Propagation -} - -// State stores container's running state -// it's part of ContainerJSONBase and returned by "inspect" command -type State struct { - Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead" - Running bool - Paused bool - Restarting bool - OOMKilled bool - Dead bool - Pid int - ExitCode int - Error string - StartedAt string - FinishedAt string - Health *Health `json:",omitempty"` -} - -// Summary contains response of Engine API: -// GET "/containers/json" -type Summary struct { - ID string `json:"Id"` - Names []string - Image string - ImageID string - Command string - Created int64 - Ports []Port - SizeRw int64 `json:",omitempty"` - SizeRootFs int64 `json:",omitempty"` - Labels map[string]string - State string - Status string - HostConfig struct { - NetworkMode string `json:",omitempty"` - Annotations map[string]string `json:",omitempty"` - } - NetworkSettings *NetworkSettingsSummary - Mounts []MountPoint -} - -// ContainerJSONBase contains response of Engine API GET "/containers/{name:.*}/json" -// for API version 1.18 and older. -// -// TODO(thaJeztah): combine ContainerJSONBase and InspectResponse into a single struct. -// The split between ContainerJSONBase (ContainerJSONBase) and InspectResponse (InspectResponse) -// was done in commit 6deaa58ba5f051039643cedceee97c8695e2af74 (https://github.com/moby/moby/pull/13675). -// ContainerJSONBase contained all fields for API < 1.19, and InspectResponse -// held fields that were added in API 1.19 and up. Given that the minimum -// supported API version is now 1.24, we no longer use the separate type. -type ContainerJSONBase struct { - ID string `json:"Id"` - Created string - Path string - Args []string - State *State - Image string - ResolvConfPath string - HostnamePath string - HostsPath string - LogPath string - Name string - RestartCount int - Driver string - Platform string - MountLabel string - ProcessLabel string - AppArmorProfile string - ExecIDs []string - HostConfig *HostConfig - GraphDriver storage.DriverData - SizeRw *int64 `json:",omitempty"` - SizeRootFs *int64 `json:",omitempty"` -} - -// InspectResponse is the response for the GET "/containers/{name:.*}/json" -// endpoint. -type InspectResponse struct { - *ContainerJSONBase - Mounts []MountPoint - Config *Config - NetworkSettings *NetworkSettings - // ImageManifestDescriptor is the descriptor of a platform-specific manifest of the image used to create the container. - ImageManifestDescriptor *ocispec.Descriptor `json:",omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/container/health.go b/vendor/github.com/docker/docker/api/types/container/health.go deleted file mode 100644 index 93663746..00000000 --- a/vendor/github.com/docker/docker/api/types/container/health.go +++ /dev/null @@ -1,26 +0,0 @@ -package container - -import "time" - -// Health states -const ( - NoHealthcheck = "none" // Indicates there is no healthcheck - Starting = "starting" // Starting indicates that the container is not yet ready - Healthy = "healthy" // Healthy indicates that the container is running correctly - Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem -) - -// Health stores information about the container's healthcheck results -type Health struct { - Status string // Status is one of [Starting], [Healthy] or [Unhealthy]. - FailingStreak int // FailingStreak is the number of consecutive failures - Log []*HealthcheckResult // Log contains the last few results (oldest first) -} - -// HealthcheckResult stores information about a single run of a healthcheck probe -type HealthcheckResult struct { - Start time.Time // Start is the time this check started - End time.Time // End is the time this check ended - ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe - Output string // Output from last check -} diff --git a/vendor/github.com/docker/docker/api/types/container/network_settings.go b/vendor/github.com/docker/docker/api/types/container/network_settings.go deleted file mode 100644 index afec0e54..00000000 --- a/vendor/github.com/docker/docker/api/types/container/network_settings.go +++ /dev/null @@ -1,56 +0,0 @@ -package container - -import ( - "github.com/docker/docker/api/types/network" - "github.com/docker/go-connections/nat" -) - -// NetworkSettings exposes the network settings in the api -type NetworkSettings struct { - NetworkSettingsBase - DefaultNetworkSettings - Networks map[string]*network.EndpointSettings -} - -// NetworkSettingsBase holds networking state for a container when inspecting it. -type NetworkSettingsBase struct { - Bridge string // Bridge contains the name of the default bridge interface iff it was set through the daemon --bridge flag. - SandboxID string // SandboxID uniquely represents a container's network stack - SandboxKey string // SandboxKey identifies the sandbox - Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port - - // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface - // - // Deprecated: This field is never set and will be removed in a future release. - HairpinMode bool - // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix - // - // Deprecated: This field is never set and will be removed in a future release. - LinkLocalIPv6Address string - // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address - // - // Deprecated: This field is never set and will be removed in a future release. - LinkLocalIPv6PrefixLen int - SecondaryIPAddresses []network.Address // Deprecated: This field is never set and will be removed in a future release. - SecondaryIPv6Addresses []network.Address // Deprecated: This field is never set and will be removed in a future release. -} - -// DefaultNetworkSettings holds network information -// during the 2 release deprecation period. -// It will be removed in Docker 1.11. -type DefaultNetworkSettings struct { - EndpointID string // EndpointID uniquely represents a service endpoint in a Sandbox - Gateway string // Gateway holds the gateway address for the network - GlobalIPv6Address string // GlobalIPv6Address holds network's global IPv6 address - GlobalIPv6PrefixLen int // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address - IPAddress string // IPAddress holds the IPv4 address for the network - IPPrefixLen int // IPPrefixLen represents mask length of network's IPv4 address - IPv6Gateway string // IPv6Gateway holds gateway address specific for IPv6 - MacAddress string // MacAddress holds the MAC address for the network -} - -// NetworkSettingsSummary provides a summary of container's networks -// in /containers/json -type NetworkSettingsSummary struct { - Networks map[string]*network.EndpointSettings -} diff --git a/vendor/github.com/docker/docker/api/types/container/stats.go b/vendor/github.com/docker/docker/api/types/container/stats.go index 3bfeb484..3b3fb131 100644 --- a/vendor/github.com/docker/docker/api/types/container/stats.go +++ b/vendor/github.com/docker/docker/api/types/container/stats.go @@ -148,15 +148,7 @@ type PidsStats struct { } // Stats is Ultimate struct aggregating all types of stats of one container -// -// Deprecated: use [StatsResponse] instead. This type will be removed in the next release. -type Stats = StatsResponse - -// StatsResponse aggregates all types of stats of one container. -type StatsResponse struct { - Name string `json:"name,omitempty"` - ID string `json:"id,omitempty"` - +type Stats struct { // Common stats Read time.Time `json:"read"` PreRead time.Time `json:"preread"` @@ -170,8 +162,20 @@ type StatsResponse struct { StorageStats StorageStats `json:"storage_stats,omitempty"` // Shared stats - CPUStats CPUStats `json:"cpu_stats,omitempty"` - PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" - MemoryStats MemoryStats `json:"memory_stats,omitempty"` - Networks map[string]NetworkStats `json:"networks,omitempty"` + CPUStats CPUStats `json:"cpu_stats,omitempty"` + PreCPUStats CPUStats `json:"precpu_stats,omitempty"` // "Pre"="Previous" + MemoryStats MemoryStats `json:"memory_stats,omitempty"` +} + +// StatsResponse is newly used Networks. +// +// TODO(thaJeztah): unify with [Stats]. This wrapper was to account for pre-api v1.21 changes, see https://github.com/moby/moby/commit/d3379946ec96fb6163cb8c4517d7d5a067045801 +type StatsResponse struct { + Stats + + Name string `json:"name,omitempty"` + ID string `json:"id,omitempty"` + + // Networks request version >=1.21 + Networks map[string]NetworkStats `json:"networks,omitempty"` } diff --git a/vendor/github.com/docker/docker/api/types/filters/errors.go b/vendor/github.com/docker/docker/api/types/filters/errors.go index b8a690d6..f52f6944 100644 --- a/vendor/github.com/docker/docker/api/types/filters/errors.go +++ b/vendor/github.com/docker/docker/api/types/filters/errors.go @@ -22,3 +22,16 @@ func (e invalidFilter) Error() string { // 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) +} 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 2085ff38..0914b2a4 100644 --- a/vendor/github.com/docker/docker/api/types/filters/parse.go +++ b/vendor/github.com/docker/docker/api/types/filters/parse.go @@ -200,6 +200,7 @@ func (args Args) Match(field, source string) bool { // 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 } @@ -210,11 +211,20 @@ func (args Args) GetBoolOrDefault(key string, defaultValue bool) (bool, error) { isFalse := fieldValues["0"] || fieldValues["false"] isTrue := fieldValues["1"] || fieldValues["true"] - if isFalse == isTrue { - // Either no or conflicting truthy/falsy value were provided + + 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 } - return isTrue, 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. diff --git a/vendor/github.com/docker/docker/api/types/storage/driver_data.go b/vendor/github.com/docker/docker/api/types/graph_driver_data.go similarity index 75% rename from vendor/github.com/docker/docker/api/types/storage/driver_data.go rename to vendor/github.com/docker/docker/api/types/graph_driver_data.go index 009e2130..ce3deb33 100644 --- a/vendor/github.com/docker/docker/api/types/storage/driver_data.go +++ b/vendor/github.com/docker/docker/api/types/graph_driver_data.go @@ -1,13 +1,13 @@ -package storage +package types // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command -// DriverData Information about the storage driver used to store the container's and +// GraphDriverData Information about the storage driver used to store the container's and // image's filesystem. // -// swagger:model DriverData -type DriverData struct { +// swagger:model GraphDriverData +type GraphDriverData struct { // Low-level storage metadata, provided as key/value pairs. // diff --git a/vendor/github.com/docker/docker/api/types/image/image_inspect.go b/vendor/github.com/docker/docker/api/types/image/image_inspect.go deleted file mode 100644 index 78e81f05..00000000 --- a/vendor/github.com/docker/docker/api/types/image/image_inspect.go +++ /dev/null @@ -1,140 +0,0 @@ -package image - -import ( - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/storage" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" -) - -// RootFS returns Image's RootFS description including the layer IDs. -type RootFS struct { - Type string `json:",omitempty"` - Layers []string `json:",omitempty"` -} - -// InspectResponse contains response of Engine API: -// GET "/images/{name:.*}/json" -type InspectResponse struct { - // ID is the content-addressable ID of an image. - // - // This identifier is a content-addressable digest calculated from the - // image's configuration (which includes the digests of layers used by - // the image). - // - // Note that this digest differs from the `RepoDigests` below, which - // holds digests of image manifests that reference the image. - ID string `json:"Id"` - - // RepoTags is a list of image names/tags in the local image cache that - // reference this image. - // - // Multiple image tags can refer to the same image, and this list may be - // empty if no tags reference the image, in which case the image is - // "untagged", in which case it can still be referenced by its ID. - RepoTags []string - - // RepoDigests is a list of content-addressable digests of locally available - // image manifests that the image is referenced from. Multiple manifests can - // refer to the same image. - // - // These digests are usually only available if the image was either pulled - // from a registry, or if the image was pushed to a registry, which is when - // the manifest is generated and its digest calculated. - RepoDigests []string - - // Parent is the ID of the parent image. - // - // Depending on how the image was created, this field may be empty and - // is only set for images that were built/created locally. This field - // is empty if the image was pulled from an image registry. - Parent string - - // Comment is an optional message that can be set when committing or - // importing the image. - Comment string - - // Created is the date and time at which the image was created, formatted in - // RFC 3339 nano-seconds (time.RFC3339Nano). - // - // This information is only available if present in the image, - // and omitted otherwise. - Created string `json:",omitempty"` - - // Container is the ID of the container that was used to create the image. - // - // Depending on how the image was created, this field may be empty. - // - // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. - Container string `json:",omitempty"` - - // ContainerConfig is an optional field containing the configuration of the - // container that was last committed when creating the image. - // - // Previous versions of Docker builder used this field to store build cache, - // and it is not in active use anymore. - // - // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. - ContainerConfig *container.Config `json:",omitempty"` - - // DockerVersion is the version of Docker that was used to build the image. - // - // Depending on how the image was created, this field may be empty. - DockerVersion string - - // Author is the name of the author that was specified when committing the - // image, or as specified through MAINTAINER (deprecated) in the Dockerfile. - Author string - Config *container.Config - - // Architecture is the hardware CPU architecture that the image runs on. - Architecture string - - // Variant is the CPU architecture variant (presently ARM-only). - Variant string `json:",omitempty"` - - // OS is the Operating System the image is built to run on. - Os string - - // OsVersion is the version of the Operating System the image is built to - // run on (especially for Windows). - OsVersion string `json:",omitempty"` - - // Size is the total size of the image including all layers it is composed of. - Size int64 - - // VirtualSize is the total size of the image including all layers it is - // composed of. - // - // Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead. - VirtualSize int64 `json:"VirtualSize,omitempty"` - - // GraphDriver holds information about the storage driver used to store the - // container's and image's filesystem. - GraphDriver storage.DriverData - - // RootFS contains information about the image's RootFS, including the - // layer IDs. - RootFS RootFS - - // Metadata of the image in the local cache. - // - // This information is local to the daemon, and not part of the image itself. - Metadata Metadata - - // Descriptor is the OCI descriptor of the image target. - // It's only set if the daemon provides a multi-platform image store. - // - // WARNING: This is experimental and may change at any time without any backward - // compatibility. - Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"` - - // Manifests is a list of image manifests available in this image. It - // provides a more detailed view of the platform-specific image manifests or - // other image-attached data like build attestations. - // - // Only available if the daemon provides a multi-platform image store. - // - // WARNING: This is experimental and may change at any time without any backward - // compatibility. - Manifests []ManifestSummary `json:"Manifests,omitempty"` -} diff --git a/vendor/github.com/docker/docker/api/types/image/opts.go b/vendor/github.com/docker/docker/api/types/image/opts.go index 919510fe..923ebe5a 100644 --- a/vendor/github.com/docker/docker/api/types/image/opts.go +++ b/vendor/github.com/docker/docker/api/types/image/opts.go @@ -38,7 +38,7 @@ type PullOptions struct { // authentication header value in base64 encoded format, or an error if the // privilege request fails. // - // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. + // Also see [github.com/docker/docker/api/types.RequestPrivilegeFunc]. PrivilegeFunc func(context.Context) (string, error) Platform string } @@ -53,7 +53,7 @@ type PushOptions struct { // authentication header value in base64 encoded format, or an error if the // privilege request fails. // - // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. + // Also see [github.com/docker/docker/api/types.RequestPrivilegeFunc]. PrivilegeFunc func(context.Context) (string, error) // Platform is an optional field that selects a specific platform to push @@ -86,31 +86,3 @@ type RemoveOptions struct { Force bool PruneChildren bool } - -// HistoryOptions holds parameters to get image history. -type HistoryOptions struct { - // Platform from the manifest list to use for history. - Platform *ocispec.Platform -} - -// LoadOptions holds parameters to load images. -type LoadOptions struct { - // Quiet suppresses progress output - Quiet bool - - // Platforms selects the platforms to load if the image is a - // multi-platform image and has multiple variants. - Platforms []ocispec.Platform -} - -type InspectOptions struct { - // Manifests returns the image manifests. - Manifests bool -} - -// SaveOptions holds parameters to save images. -type SaveOptions struct { - // Platforms selects the platforms to save if the image is a - // multi-platform image and has multiple variants. - Platforms []ocispec.Platform -} 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 c5ae6ab9..e87e216a 100644 --- a/vendor/github.com/docker/docker/api/types/image/summary.go +++ b/vendor/github.com/docker/docker/api/types/image/summary.go @@ -1,7 +1,5 @@ package image -import ocispec "github.com/opencontainers/image-spec/specs-go/v1" - type Summary struct { // Number of containers using this image. Includes both stopped and running @@ -44,13 +42,6 @@ type Summary struct { // Required: true ParentID string `json:"ParentId"` - // Descriptor is the OCI descriptor of the image target. - // It's only set if the daemon provides a multi-platform image store. - // - // WARNING: This is experimental and may change at any time without any backward - // compatibility. - Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"` - // Manifests is a list of image manifests available in this image. It // provides a more detailed view of the platform-specific image manifests or // other image-attached data like build attestations. diff --git a/vendor/github.com/docker/docker/api/types/mount/mount.go b/vendor/github.com/docker/docker/api/types/mount/mount.go index d98dbec9..c68dcf65 100644 --- a/vendor/github.com/docker/docker/api/types/mount/mount.go +++ b/vendor/github.com/docker/docker/api/types/mount/mount.go @@ -19,8 +19,6 @@ const ( TypeNamedPipe Type = "npipe" // TypeCluster is the type for Swarm Cluster Volumes. TypeCluster Type = "cluster" - // TypeImage is the type for mounting another image's filesystem - TypeImage Type = "image" ) // Mount represents a mount (volume). @@ -36,7 +34,6 @@ type Mount struct { BindOptions *BindOptions `json:",omitempty"` VolumeOptions *VolumeOptions `json:",omitempty"` - ImageOptions *ImageOptions `json:",omitempty"` TmpfsOptions *TmpfsOptions `json:",omitempty"` ClusterOptions *ClusterOptions `json:",omitempty"` } @@ -103,10 +100,6 @@ type VolumeOptions struct { DriverConfig *Driver `json:",omitempty"` } -type ImageOptions struct { - Subpath string `json:",omitempty"` -} - // Driver represents a volume driver. type Driver struct { Name string `json:",omitempty"` diff --git a/vendor/github.com/docker/docker/api/types/network/endpoint.go b/vendor/github.com/docker/docker/api/types/network/endpoint.go index 167ac70a..0fbb40b3 100644 --- a/vendor/github.com/docker/docker/api/types/network/endpoint.go +++ b/vendor/github.com/docker/docker/api/types/network/endpoint.go @@ -19,12 +19,6 @@ type EndpointSettings struct { // generated address). MacAddress string DriverOpts map[string]string - - // GwPriority determines which endpoint will provide the default gateway - // for the container. The endpoint with the highest priority will be used. - // If multiple endpoints have the same priority, they are lexicographically - // sorted based on their network name, and the one that sorts first is picked. - GwPriority int // Operational data NetworkID string EndpointID string diff --git a/vendor/github.com/docker/docker/api/types/network/network.go b/vendor/github.com/docker/docker/api/types/network/network.go index d34b8ab7..c8db97a7 100644 --- a/vendor/github.com/docker/docker/api/types/network/network.go +++ b/vendor/github.com/docker/docker/api/types/network/network.go @@ -33,7 +33,6 @@ type CreateRequest struct { type CreateOptions struct { Driver string // Driver is the driver-name used to create the network (e.g. `bridge`, `overlay`) Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level). - EnableIPv4 *bool `json:",omitempty"` // EnableIPv4 represents whether to enable IPv4. EnableIPv6 *bool `json:",omitempty"` // EnableIPv6 represents whether to enable IPv6. IPAM *IPAM // IPAM is the network's IP Address Management. Internal bool // Internal represents if the network is used internal only. @@ -77,8 +76,7 @@ type Inspect struct { Created time.Time // Created is the time the network created Scope string // Scope describes the level at which the network exists (e.g. `swarm` for cluster-wide or `local` for machine level) Driver string // Driver is the Driver name used to create the network (e.g. `bridge`, `overlay`) - EnableIPv4 bool // EnableIPv4 represents whether IPv4 is enabled - EnableIPv6 bool // EnableIPv6 represents whether IPv6 is enabled + EnableIPv6 bool // EnableIPv6 represents whether to enable IPv6 IPAM IPAM // IPAM is the network's IP Address Management Internal bool // Internal represents if the network is used internal only Attachable bool // Attachable represents if the global scope is manually attachable by regular containers from workers in swarm mode. diff --git a/vendor/github.com/docker/docker/api/types/container/port.go b/vendor/github.com/docker/docker/api/types/port.go similarity index 96% rename from vendor/github.com/docker/docker/api/types/container/port.go rename to vendor/github.com/docker/docker/api/types/port.go index 895043cf..d9123474 100644 --- a/vendor/github.com/docker/docker/api/types/container/port.go +++ b/vendor/github.com/docker/docker/api/types/port.go @@ -1,4 +1,4 @@ -package container +package types // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command diff --git a/vendor/github.com/docker/docker/api/types/registry/authconfig.go b/vendor/github.com/docker/docker/api/types/registry/authconfig.go index ebd5e4b9..8e383f6e 100644 --- a/vendor/github.com/docker/docker/api/types/registry/authconfig.go +++ b/vendor/github.com/docker/docker/api/types/registry/authconfig.go @@ -1,29 +1,17 @@ package registry // import "github.com/docker/docker/api/types/registry" import ( - "context" "encoding/base64" "encoding/json" - "fmt" "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" -// RequestAuthConfig is a function interface that clients can supply -// to retry operations after getting an authorization error. -// -// The function must return the [AuthHeader] value ([AuthConfig]), encoded -// in base64url format ([RFC4648, section 5]), which can be decoded by -// [DecodeAuthConfig]. -// -// It must return an error if the privilege request fails. -// -// [RFC4648, section 5]: https://tools.ietf.org/html/rfc4648#section-5 -type RequestAuthConfig func(context.Context) (string, error) - // AuthConfig contains authorization information for connecting to a Registry. type AuthConfig struct { Username string `json:"username,omitempty"` @@ -97,7 +85,7 @@ func decodeAuthConfigFromReader(rdr io.Reader) (*AuthConfig, error) { } func invalid(err error) error { - return errInvalidParameter{fmt.Errorf("invalid X-Registry-Auth header: %w", err)} + return errInvalidParameter{errors.Wrap(err, "invalid X-Registry-Auth header")} } type errInvalidParameter struct{ error } diff --git a/vendor/github.com/docker/docker/api/types/registry/registry.go b/vendor/github.com/docker/docker/api/types/registry/registry.go index b0a4d604..75ee07b1 100644 --- a/vendor/github.com/docker/docker/api/types/registry/registry.go +++ b/vendor/github.com/docker/docker/api/types/registry/registry.go @@ -9,29 +9,11 @@ import ( // ServiceConfig stores daemon registry services configuration. type ServiceConfig struct { - AllowNondistributableArtifactsCIDRs []*NetIPNet `json:"AllowNondistributableArtifactsCIDRs,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. - AllowNondistributableArtifactsHostnames []string `json:"AllowNondistributableArtifactsHostnames,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. - - InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` - IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` - Mirrors []string -} - -// MarshalJSON implements a custom marshaler to include legacy fields -// in API responses. -func (sc ServiceConfig) MarshalJSON() ([]byte, error) { - tmp := map[string]interface{}{ - "InsecureRegistryCIDRs": sc.InsecureRegistryCIDRs, - "IndexConfigs": sc.IndexConfigs, - "Mirrors": sc.Mirrors, - } - if sc.AllowNondistributableArtifactsCIDRs != nil { - tmp["AllowNondistributableArtifactsCIDRs"] = nil - } - if sc.AllowNondistributableArtifactsHostnames != nil { - tmp["AllowNondistributableArtifactsHostnames"] = nil - } - return json.Marshal(tmp) + AllowNondistributableArtifactsCIDRs []*NetIPNet + AllowNondistributableArtifactsHostnames []string + InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"` + IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"` + Mirrors []string } // NetIPNet is the net.IPNet type, which can be marshalled and diff --git a/vendor/github.com/docker/docker/api/types/registry/search.go b/vendor/github.com/docker/docker/api/types/registry/search.go index 994ca4c6..a0a1eec5 100644 --- a/vendor/github.com/docker/docker/api/types/registry/search.go +++ b/vendor/github.com/docker/docker/api/types/registry/search.go @@ -10,12 +10,11 @@ import ( type SearchOptions struct { RegistryAuth string - // PrivilegeFunc is a function that clients can supply to retry operations - // after getting an authorization error. This function returns the registry - // authentication header value in base64 encoded format, or an error if the - // privilege request fails. + // PrivilegeFunc is a [types.RequestPrivilegeFunc] the client can + // supply to retry operations after getting an authorization error. // - // For details, refer to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. + // It must return the registry authentication header value in base64 + // format, or an error if the privilege request fails. PrivilegeFunc func(context.Context) (string, error) Filters filters.Args Limit int diff --git a/vendor/github.com/docker/docker/api/types/system/info.go b/vendor/github.com/docker/docker/api/types/system/info.go index 8a2444da..c66a2afb 100644 --- a/vendor/github.com/docker/docker/api/types/system/info.go +++ b/vendor/github.com/docker/docker/api/types/system/info.go @@ -29,8 +29,8 @@ type Info struct { CPUSet bool PidsLimit bool IPv4Forwarding bool - BridgeNfIptables bool `json:"BridgeNfIptables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release. - BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` // Deprecated: netfilter module is now loaded on-demand and no longer during daemon startup, making this field obsolete. This field is always false and will be removed in the next release. + BridgeNfIptables bool + BridgeNfIP6tables bool `json:"BridgeNfIp6tables"` Debug bool NFd int OomKillDisable bool @@ -137,13 +137,8 @@ type PluginsInfo struct { // Commit holds the Git-commit (SHA1) that a binary was built from, as reported // in the version-string of external tools, such as containerd, or runC. type Commit struct { - // ID is the actual commit ID or version of external tool. - ID string - - // Expected is the commit ID of external tool expected by dockerd as set at build time. - // - // Deprecated: this field is no longer used in API v1.49, but kept for backward-compatibility with older API versions. - Expected string + ID string // ID is the actual commit ID of external tool. + Expected string // Expected is the commit ID of external tool expected by dockerd as set at build time. } // NetworkAddressPool is a temp struct used by [Info] struct. diff --git a/vendor/github.com/docker/docker/api/types/types.go b/vendor/github.com/docker/docker/api/types/types.go index 82ae339c..ea55813e 100644 --- a/vendor/github.com/docker/docker/api/types/types.go +++ b/vendor/github.com/docker/docker/api/types/types.go @@ -6,8 +6,11 @@ import ( "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/image" + "github.com/docker/docker/api/types/mount" + "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/volume" + "github.com/docker/go-connections/nat" ) const ( @@ -18,6 +21,145 @@ const ( MediaTypeMultiplexedStream = "application/vnd.docker.multiplexed-stream" ) +// RootFS returns Image's RootFS description including the layer IDs. +type RootFS struct { + Type string `json:",omitempty"` + Layers []string `json:",omitempty"` +} + +// ImageInspect contains response of Engine API: +// GET "/images/{name:.*}/json" +type ImageInspect struct { + // ID is the content-addressable ID of an image. + // + // This identifier is a content-addressable digest calculated from the + // image's configuration (which includes the digests of layers used by + // the image). + // + // Note that this digest differs from the `RepoDigests` below, which + // holds digests of image manifests that reference the image. + ID string `json:"Id"` + + // RepoTags is a list of image names/tags in the local image cache that + // reference this image. + // + // Multiple image tags can refer to the same image, and this list may be + // empty if no tags reference the image, in which case the image is + // "untagged", in which case it can still be referenced by its ID. + RepoTags []string + + // RepoDigests is a list of content-addressable digests of locally available + // image manifests that the image is referenced from. Multiple manifests can + // refer to the same image. + // + // These digests are usually only available if the image was either pulled + // from a registry, or if the image was pushed to a registry, which is when + // the manifest is generated and its digest calculated. + RepoDigests []string + + // Parent is the ID of the parent image. + // + // Depending on how the image was created, this field may be empty and + // is only set for images that were built/created locally. This field + // is empty if the image was pulled from an image registry. + Parent string + + // Comment is an optional message that can be set when committing or + // importing the image. + Comment string + + // Created is the date and time at which the image was created, formatted in + // RFC 3339 nano-seconds (time.RFC3339Nano). + // + // This information is only available if present in the image, + // and omitted otherwise. + Created string `json:",omitempty"` + + // Container is the ID of the container that was used to create the image. + // + // Depending on how the image was created, this field may be empty. + // + // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. + Container string `json:",omitempty"` + + // ContainerConfig is an optional field containing the configuration of the + // container that was last committed when creating the image. + // + // Previous versions of Docker builder used this field to store build cache, + // and it is not in active use anymore. + // + // Deprecated: this field is omitted in API v1.45, but kept for backward compatibility. + ContainerConfig *container.Config `json:",omitempty"` + + // DockerVersion is the version of Docker that was used to build the image. + // + // Depending on how the image was created, this field may be empty. + DockerVersion string + + // Author is the name of the author that was specified when committing the + // image, or as specified through MAINTAINER (deprecated) in the Dockerfile. + Author string + Config *container.Config + + // Architecture is the hardware CPU architecture that the image runs on. + Architecture string + + // Variant is the CPU architecture variant (presently ARM-only). + Variant string `json:",omitempty"` + + // OS is the Operating System the image is built to run on. + Os string + + // OsVersion is the version of the Operating System the image is built to + // run on (especially for Windows). + OsVersion string `json:",omitempty"` + + // Size is the total size of the image including all layers it is composed of. + Size int64 + + // VirtualSize is the total size of the image including all layers it is + // composed of. + // + // Deprecated: this field is omitted in API v1.44, but kept for backward compatibility. Use Size instead. + VirtualSize int64 `json:"VirtualSize,omitempty"` + + // GraphDriver holds information about the storage driver used to store the + // container's and image's filesystem. + GraphDriver GraphDriverData + + // RootFS contains information about the image's RootFS, including the + // layer IDs. + RootFS RootFS + + // Metadata of the image in the local cache. + // + // This information is local to the daemon, and not part of the image itself. + Metadata image.Metadata +} + +// Container contains response of Engine API: +// GET "/containers/json" +type Container struct { + ID string `json:"Id"` + Names []string + Image string + ImageID string + Command string + Created int64 + Ports []Port + SizeRw int64 `json:",omitempty"` + SizeRootFs int64 `json:",omitempty"` + Labels map[string]string + State string + Status string + HostConfig struct { + NetworkMode string `json:",omitempty"` + Annotations map[string]string `json:",omitempty"` + } + NetworkSettings *SummaryNetworkSettings + Mounts []MountPoint +} + // Ping contains response of Engine API: // GET "/_ping" type Ping struct { @@ -63,6 +205,176 @@ type Version struct { BuildTime string `json:",omitempty"` } +// HealthcheckResult stores information about a single run of a healthcheck probe +type HealthcheckResult struct { + Start time.Time // Start is the time this check started + End time.Time // End is the time this check ended + ExitCode int // ExitCode meanings: 0=healthy, 1=unhealthy, 2=reserved (considered unhealthy), else=error running probe + Output string // Output from last check +} + +// Health states +const ( + NoHealthcheck = "none" // Indicates there is no healthcheck + Starting = "starting" // Starting indicates that the container is not yet ready + Healthy = "healthy" // Healthy indicates that the container is running correctly + Unhealthy = "unhealthy" // Unhealthy indicates that the container has a problem +) + +// Health stores information about the container's healthcheck results +type Health struct { + Status string // Status is one of Starting, Healthy or Unhealthy + FailingStreak int // FailingStreak is the number of consecutive failures + Log []*HealthcheckResult // Log contains the last few results (oldest first) +} + +// ContainerState stores container's running state +// it's part of ContainerJSONBase and will return by "inspect" command +type ContainerState struct { + Status string // String representation of the container state. Can be one of "created", "running", "paused", "restarting", "removing", "exited", or "dead" + Running bool + Paused bool + Restarting bool + OOMKilled bool + Dead bool + Pid int + ExitCode int + Error string + StartedAt string + FinishedAt string + Health *Health `json:",omitempty"` +} + +// ContainerJSONBase contains response of Engine API: +// GET "/containers/{name:.*}/json" +type ContainerJSONBase struct { + ID string `json:"Id"` + Created string + Path string + Args []string + State *ContainerState + Image string + ResolvConfPath string + HostnamePath string + HostsPath string + LogPath string + Node *ContainerNode `json:",omitempty"` // Deprecated: Node was only propagated by Docker Swarm standalone API. It sill be removed in the next release. + Name string + RestartCount int + Driver string + Platform string + MountLabel string + ProcessLabel string + AppArmorProfile string + ExecIDs []string + HostConfig *container.HostConfig + GraphDriver GraphDriverData + SizeRw *int64 `json:",omitempty"` + SizeRootFs *int64 `json:",omitempty"` +} + +// ContainerJSON is newly used struct along with MountPoint +type ContainerJSON struct { + *ContainerJSONBase + Mounts []MountPoint + Config *container.Config + NetworkSettings *NetworkSettings +} + +// NetworkSettings exposes the network settings in the api +type NetworkSettings struct { + NetworkSettingsBase + DefaultNetworkSettings + Networks map[string]*network.EndpointSettings +} + +// SummaryNetworkSettings provides a summary of container's networks +// in /containers/json +type SummaryNetworkSettings struct { + Networks map[string]*network.EndpointSettings +} + +// NetworkSettingsBase holds networking state for a container when inspecting it. +type NetworkSettingsBase struct { + Bridge string // Bridge contains the name of the default bridge interface iff it was set through the daemon --bridge flag. + SandboxID string // SandboxID uniquely represents a container's network stack + SandboxKey string // SandboxKey identifies the sandbox + Ports nat.PortMap // Ports is a collection of PortBinding indexed by Port + + // HairpinMode specifies if hairpin NAT should be enabled on the virtual interface + // + // Deprecated: This field is never set and will be removed in a future release. + HairpinMode bool + // LinkLocalIPv6Address is an IPv6 unicast address using the link-local prefix + // + // Deprecated: This field is never set and will be removed in a future release. + LinkLocalIPv6Address string + // LinkLocalIPv6PrefixLen is the prefix length of an IPv6 unicast address + // + // Deprecated: This field is never set and will be removed in a future release. + LinkLocalIPv6PrefixLen int + SecondaryIPAddresses []network.Address // Deprecated: This field is never set and will be removed in a future release. + SecondaryIPv6Addresses []network.Address // Deprecated: This field is never set and will be removed in a future release. +} + +// DefaultNetworkSettings holds network information +// during the 2 release deprecation period. +// It will be removed in Docker 1.11. +type DefaultNetworkSettings struct { + EndpointID string // EndpointID uniquely represents a service endpoint in a Sandbox + Gateway string // Gateway holds the gateway address for the network + GlobalIPv6Address string // GlobalIPv6Address holds network's global IPv6 address + GlobalIPv6PrefixLen int // GlobalIPv6PrefixLen represents mask length of network's global IPv6 address + IPAddress string // IPAddress holds the IPv4 address for the network + IPPrefixLen int // IPPrefixLen represents mask length of network's IPv4 address + IPv6Gateway string // IPv6Gateway holds gateway address specific for IPv6 + MacAddress string // MacAddress holds the MAC address for the network +} + +// MountPoint represents a mount point configuration inside the container. +// This is used for reporting the mountpoints in use by a container. +type MountPoint struct { + // Type is the type of mount, see `Type` definitions in + // github.com/docker/docker/api/types/mount.Type + Type mount.Type `json:",omitempty"` + + // Name is the name reference to the underlying data defined by `Source` + // e.g., the volume name. + Name string `json:",omitempty"` + + // Source is the source location of the mount. + // + // For volumes, this contains the storage location of the volume (within + // `/var/lib/docker/volumes/`). For bind-mounts, and `npipe`, this contains + // the source (host) part of the bind-mount. For `tmpfs` mount points, this + // field is empty. + Source string + + // Destination is the path relative to the container root (`/`) where the + // Source is mounted inside the container. + Destination string + + // Driver is the volume driver used to create the volume (if it is a volume). + Driver string `json:",omitempty"` + + // Mode is a comma separated list of options supplied by the user when + // creating the bind/volume mount. + // + // The default is platform-specific (`"z"` on Linux, empty on Windows). + Mode string + + // RW indicates whether the mount is mounted writable (read-write). + RW bool + + // Propagation describes how mounts are propagated from the host into the + // mount point, and vice-versa. Refer to the Linux kernel documentation + // for details: + // https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt + // + // This field is not used on Windows. + Propagation mount.Propagation +} + // DiskUsageObject represents an object type used for disk usage query filtering. type DiskUsageObject string @@ -89,7 +401,7 @@ type DiskUsageOptions struct { type DiskUsage struct { LayersSize int64 Images []*image.Summary - Containers []*container.Summary + Containers []*Container Volumes []*volume.Volume BuildCache []*BuildCache BuilderSize int64 `json:",omitempty"` // Deprecated: deprecated in API 1.38, and no longer used since API 1.40. @@ -169,11 +481,9 @@ type BuildCache struct { // BuildCachePruneOptions hold parameters to prune the build cache type BuildCachePruneOptions struct { - All bool - ReservedSpace int64 - MaxUsedSpace int64 - MinFreeSpace int64 - Filters filters.Args + All bool + KeepStorage int64 + Filters filters.Args - KeepStorage int64 // Deprecated: deprecated in API 1.48. + // FIXME(thaJeztah): add new options; see https://github.com/moby/moby/issues/48639 } diff --git a/vendor/github.com/docker/docker/api/types/types_deprecated.go b/vendor/github.com/docker/docker/api/types/types_deprecated.go index 170a65b8..43ffe104 100644 --- a/vendor/github.com/docker/docker/api/types/types_deprecated.go +++ b/vendor/github.com/docker/docker/api/types/types_deprecated.go @@ -1,109 +1,210 @@ package types import ( - "context" - "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types/events" "github.com/docker/docker/api/types/image" - "github.com/docker/docker/api/types/storage" + "github.com/docker/docker/api/types/network" + "github.com/docker/docker/api/types/registry" + "github.com/docker/docker/api/types/volume" ) -// ContainerJSONBase contains response of Engine API GET "/containers/{name:.*}/json" -// for API version 1.18 and older. +// ImagesPruneReport contains the response for Engine API: +// POST "/images/prune" // -// Deprecated: use [container.InspectResponse] or [container.ContainerJSONBase]. It will be removed in the next release. -type ContainerJSONBase = container.ContainerJSONBase +// Deprecated: use [image.PruneReport]. +type ImagesPruneReport = image.PruneReport -// ContainerJSON is the response for the GET "/containers/{name:.*}/json" -// endpoint. +// VolumesPruneReport contains the response for Engine API: +// POST "/volumes/prune". // -// Deprecated: use [container.InspectResponse]. It will be removed in the next release. -type ContainerJSON = container.InspectResponse +// Deprecated: use [volume.PruneReport]. +type VolumesPruneReport = volume.PruneReport -// Container contains response of Engine API: -// GET "/containers/json" +// NetworkCreateRequest is the request message sent to the server for network create call. // -// Deprecated: use [container.Summary]. -type Container = container.Summary +// Deprecated: use [network.CreateRequest]. +type NetworkCreateRequest = network.CreateRequest -// ContainerState stores container's running state +// NetworkCreate is the expected body of the "create network" http request message // -// Deprecated: use [container.State]. -type ContainerState = container.State +// Deprecated: use [network.CreateOptions]. +type NetworkCreate = network.CreateOptions -// NetworkSettings exposes the network settings in the api. +// NetworkListOptions holds parameters to filter the list of networks with. // -// Deprecated: use [container.NetworkSettings]. -type NetworkSettings = container.NetworkSettings +// Deprecated: use [network.ListOptions]. +type NetworkListOptions = network.ListOptions -// NetworkSettingsBase holds networking state for a container when inspecting it. +// NetworkCreateResponse is the response message sent by the server for network create call. // -// Deprecated: use [container.NetworkSettingsBase]. -type NetworkSettingsBase = container.NetworkSettingsBase +// Deprecated: use [network.CreateResponse]. +type NetworkCreateResponse = network.CreateResponse -// DefaultNetworkSettings holds network information -// during the 2 release deprecation period. -// It will be removed in Docker 1.11. +// NetworkInspectOptions holds parameters to inspect network. // -// Deprecated: use [container.DefaultNetworkSettings]. -type DefaultNetworkSettings = container.DefaultNetworkSettings +// Deprecated: use [network.InspectOptions]. +type NetworkInspectOptions = network.InspectOptions -// SummaryNetworkSettings provides a summary of container's networks -// in /containers/json. +// NetworkConnect represents the data to be used to connect a container to the network // -// Deprecated: use [container.NetworkSettingsSummary]. -type SummaryNetworkSettings = container.NetworkSettingsSummary +// Deprecated: use [network.ConnectOptions]. +type NetworkConnect = network.ConnectOptions -// Health states -const ( - NoHealthcheck = container.NoHealthcheck // Deprecated: use [container.NoHealthcheck]. - Starting = container.Starting // Deprecated: use [container.Starting]. - Healthy = container.Healthy // Deprecated: use [container.Healthy]. - Unhealthy = container.Unhealthy // Deprecated: use [container.Unhealthy]. -) - -// Health stores information about the container's healthcheck results. +// NetworkDisconnect represents the data to be used to disconnect a container from the network // -// Deprecated: use [container.Health]. -type Health = container.Health +// Deprecated: use [network.DisconnectOptions]. +type NetworkDisconnect = network.DisconnectOptions -// HealthcheckResult stores information about a single run of a healthcheck probe. +// EndpointResource contains network resources allocated and used for a container in a network. // -// Deprecated: use [container.HealthcheckResult]. -type HealthcheckResult = container.HealthcheckResult +// Deprecated: use [network.EndpointResource]. +type EndpointResource = network.EndpointResource -// MountPoint represents a mount point configuration inside the container. -// This is used for reporting the mountpoints in use by a container. +// NetworkResource is the body of the "get network" http response message/ // -// Deprecated: use [container.MountPoint]. -type MountPoint = container.MountPoint +// Deprecated: use [network.Inspect] or [network.Summary] (for list operations). +type NetworkResource = network.Inspect -// Port An open port on a container +// NetworksPruneReport contains the response for Engine API: +// POST "/networks/prune" // -// Deprecated: use [container.Port]. -type Port = container.Port +// Deprecated: use [network.PruneReport]. +type NetworksPruneReport = network.PruneReport -// GraphDriverData Information about the storage driver used to store the container's and -// image's filesystem. +// ExecConfig is a small subset of the Config struct that holds the configuration +// for the exec feature of docker. // -// Deprecated: use [storage.DriverData]. -type GraphDriverData = storage.DriverData +// Deprecated: use [container.ExecOptions]. +type ExecConfig = container.ExecOptions -// RootFS returns Image's RootFS description including the layer IDs. +// ExecStartCheck is a temp struct used by execStart +// Config fields is part of ExecConfig in runconfig package // -// Deprecated: use [image.RootFS]. -type RootFS = image.RootFS +// Deprecated: use [container.ExecStartOptions] or [container.ExecAttachOptions]. +type ExecStartCheck = container.ExecStartOptions -// ImageInspect contains response of Engine API: -// GET "/images/{name:.*}/json" +// ContainerExecInspect holds information returned by exec inspect. // -// Deprecated: use [image.InspectResponse]. -type ImageInspect = image.InspectResponse +// Deprecated: use [container.ExecInspect]. +type ContainerExecInspect = container.ExecInspect -// RequestPrivilegeFunc is a function interface that clients can supply to -// retry operations after getting an authorization error. -// This function returns the registry authentication header value in base64 -// format, or an error if the privilege request fails. +// ContainersPruneReport contains the response for Engine API: +// POST "/containers/prune" // -// Deprecated: moved to [github.com/docker/docker/api/types/registry.RequestAuthConfig]. -type RequestPrivilegeFunc func(context.Context) (string, error) +// Deprecated: use [container.PruneReport]. +type ContainersPruneReport = container.PruneReport + +// ContainerPathStat is used to encode the header from +// GET "/containers/{name:.*}/archive" +// "Name" is the file or directory name. +// +// Deprecated: use [container.PathStat]. +type ContainerPathStat = container.PathStat + +// CopyToContainerOptions holds information +// about files to copy into a container. +// +// Deprecated: use [container.CopyToContainerOptions], +type CopyToContainerOptions = container.CopyToContainerOptions + +// ContainerStats contains response of Engine API: +// GET "/stats" +// +// Deprecated: use [container.StatsResponseReader]. +type ContainerStats = container.StatsResponseReader + +// ThrottlingData stores CPU throttling stats of one running container. +// Not used on Windows. +// +// Deprecated: use [container.ThrottlingData]. +type ThrottlingData = container.ThrottlingData + +// CPUUsage stores All CPU stats aggregated since container inception. +// +// Deprecated: use [container.CPUUsage]. +type CPUUsage = container.CPUUsage + +// CPUStats aggregates and wraps all CPU related info of container +// +// Deprecated: use [container.CPUStats]. +type CPUStats = container.CPUStats + +// MemoryStats aggregates all memory stats since container inception on Linux. +// Windows returns stats for commit and private working set only. +// +// Deprecated: use [container.MemoryStats]. +type MemoryStats = container.MemoryStats + +// BlkioStatEntry is one small entity to store a piece of Blkio stats +// Not used on Windows. +// +// Deprecated: use [container.BlkioStatEntry]. +type BlkioStatEntry = container.BlkioStatEntry + +// BlkioStats stores All IO service stats for data read and write. +// This is a Linux specific structure as the differences between expressing +// block I/O on Windows and Linux are sufficiently significant to make +// little sense attempting to morph into a combined structure. +// +// Deprecated: use [container.BlkioStats]. +type BlkioStats = container.BlkioStats + +// StorageStats is the disk I/O stats for read/write on Windows. +// +// Deprecated: use [container.StorageStats]. +type StorageStats = container.StorageStats + +// NetworkStats aggregates the network stats of one container +// +// Deprecated: use [container.NetworkStats]. +type NetworkStats = container.NetworkStats + +// PidsStats contains the stats of a container's pids +// +// Deprecated: use [container.PidsStats]. +type PidsStats = container.PidsStats + +// Stats is Ultimate struct aggregating all types of stats of one container +// +// Deprecated: use [container.Stats]. +type Stats = container.Stats + +// StatsJSON is newly used Networks +// +// Deprecated: use [container.StatsResponse]. +type StatsJSON = container.StatsResponse + +// EventsOptions holds parameters to filter events with. +// +// Deprecated: use [events.ListOptions]. +type EventsOptions = events.ListOptions + +// ImageSearchOptions holds parameters to search images with. +// +// Deprecated: use [registry.SearchOptions]. +type ImageSearchOptions = registry.SearchOptions + +// ImageImportSource holds source information for ImageImport +// +// Deprecated: use [image.ImportSource]. +type ImageImportSource image.ImportSource + +// ImageLoadResponse returns information to the client about a load process. +// +// Deprecated: use [image.LoadResponse]. +type ImageLoadResponse = image.LoadResponse + +// ContainerNode stores information about the node that a container +// is running on. It's only used by the Docker Swarm standalone API. +// +// Deprecated: ContainerNode was used for the classic Docker Swarm standalone API. It will be removed in the next release. +type ContainerNode struct { + ID string + IPAddress string `json:"IP"` + Addr string + Name string + Cpus int + Memory int64 + Labels map[string]string +} diff --git a/vendor/github.com/docker/docker/client/build_prune.go b/vendor/github.com/docker/docker/client/build_prune.go index 9a99d097..1a830f41 100644 --- a/vendor/github.com/docker/docker/client/build_prune.go +++ b/vendor/github.com/docker/docker/client/build_prune.go @@ -17,23 +17,13 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru return nil, err } + report := types.BuildCachePruneReport{} + query := url.Values{} if opts.All { query.Set("all", "1") } - - if opts.KeepStorage != 0 { - query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage))) - } - if opts.ReservedSpace != 0 { - query.Set("reserved-space", strconv.Itoa(int(opts.ReservedSpace))) - } - if opts.MaxUsedSpace != 0 { - query.Set("max-used-space", strconv.Itoa(int(opts.MaxUsedSpace))) - } - if opts.MinFreeSpace != 0 { - query.Set("min-free-space", strconv.Itoa(int(opts.MinFreeSpace))) - } + query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage))) f, err := filters.ToJSON(opts.Filters) if err != nil { return nil, errors.Wrap(err, "prune could not marshal filters option") @@ -47,7 +37,6 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts types.BuildCachePru return nil, err } - report := types.BuildCachePruneReport{} if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { return nil, errors.Wrap(err, "error retrieving disk usage") } diff --git a/vendor/github.com/docker/docker/client/checkpoint_create.go b/vendor/github.com/docker/docker/client/checkpoint_create.go index 7b06fee3..9746d288 100644 --- a/vendor/github.com/docker/docker/client/checkpoint_create.go +++ b/vendor/github.com/docker/docker/client/checkpoint_create.go @@ -7,13 +7,8 @@ import ( ) // CheckpointCreate creates a checkpoint from the given container with the given name -func (cli *Client) CheckpointCreate(ctx context.Context, containerID string, options checkpoint.CreateOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - - resp, err := cli.post(ctx, "/containers/"+containerID+"/checkpoints", nil, options, nil) +func (cli *Client) CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error { + resp, err := cli.post(ctx, "/containers/"+container+"/checkpoints", nil, options, nil) ensureReaderClosed(resp) return err } diff --git a/vendor/github.com/docker/docker/client/checkpoint_delete.go b/vendor/github.com/docker/docker/client/checkpoint_delete.go index d15162ea..b968c2b2 100644 --- a/vendor/github.com/docker/docker/client/checkpoint_delete.go +++ b/vendor/github.com/docker/docker/client/checkpoint_delete.go @@ -9,11 +9,6 @@ import ( // CheckpointDelete deletes the checkpoint with the given name from the given container func (cli *Client) CheckpointDelete(ctx context.Context, containerID string, options checkpoint.DeleteOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if options.CheckpointDir != "" { query.Set("dir", options.CheckpointDir) diff --git a/vendor/github.com/docker/docker/client/client.go b/vendor/github.com/docker/docker/client/client.go index c980b66a..46832d8a 100644 --- a/vendor/github.com/docker/docker/client/client.go +++ b/vendor/github.com/docker/docker/client/client.go @@ -99,9 +99,6 @@ const DummyHost = "api.moby.localhost" // recent version before negotiation was introduced. const fallbackAPIVersion = "1.24" -// Ensure that Client always implements APIClient. -var _ APIClient = &Client{} - // Client is the API client that performs all operations // against a docker server. type Client struct { @@ -307,7 +304,8 @@ func (cli *Client) getAPIPath(ctx context.Context, p string, query url.Values) s var apiPath string _ = cli.checkVersion(ctx) if cli.version != "" { - apiPath = path.Join(cli.basePath, "/v"+strings.TrimPrefix(cli.version, "v"), p) + v := strings.TrimPrefix(cli.version, "v") + apiPath = path.Join(cli.basePath, "/v"+v, p) } else { apiPath = path.Join(cli.basePath, p) } @@ -452,10 +450,6 @@ func (cli *Client) dialerFromTransport() func(context.Context, string, string) ( // // ["docker dial-stdio"]: https://github.com/docker/cli/pull/1014 func (cli *Client) Dialer() func(context.Context) (net.Conn, error) { - return cli.dialer() -} - -func (cli *Client) dialer() func(context.Context) (net.Conn, error) { return func(ctx context.Context) (net.Conn, error) { if dialFn := cli.dialerFromTransport(); dialFn != nil { return dialFn(ctx, cli.proto, cli.addr) diff --git a/vendor/github.com/docker/docker/client/config_inspect.go b/vendor/github.com/docker/docker/client/config_inspect.go index 9a16b3d4..2c6c7cb3 100644 --- a/vendor/github.com/docker/docker/client/config_inspect.go +++ b/vendor/github.com/docker/docker/client/config_inspect.go @@ -11,9 +11,8 @@ import ( // ConfigInspectWithRaw returns the config information with raw data func (cli *Client) ConfigInspectWithRaw(ctx context.Context, id string) (swarm.Config, []byte, error) { - id, err := trimID("contig", id) - if err != nil { - return swarm.Config{}, nil, err + if id == "" { + return swarm.Config{}, nil, objectNotFoundError{object: "config", id: id} } if err := cli.NewVersionError(ctx, "1.30", "config inspect"); err != nil { return swarm.Config{}, nil, err diff --git a/vendor/github.com/docker/docker/client/config_remove.go b/vendor/github.com/docker/docker/client/config_remove.go index a2955c68..d05b0113 100644 --- a/vendor/github.com/docker/docker/client/config_remove.go +++ b/vendor/github.com/docker/docker/client/config_remove.go @@ -4,10 +4,6 @@ import "context" // ConfigRemove removes a config. func (cli *Client) ConfigRemove(ctx context.Context, id string) error { - id, err := trimID("config", id) - if err != nil { - return err - } if err := cli.NewVersionError(ctx, "1.30", "config remove"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/config_update.go b/vendor/github.com/docker/docker/client/config_update.go index ddb219cf..6995861d 100644 --- a/vendor/github.com/docker/docker/client/config_update.go +++ b/vendor/github.com/docker/docker/client/config_update.go @@ -9,10 +9,6 @@ import ( // ConfigUpdate attempts to update a config func (cli *Client) ConfigUpdate(ctx context.Context, id string, version swarm.Version, config swarm.ConfigSpec) error { - id, err := trimID("config", id) - if err != nil { - return err - } if err := cli.NewVersionError(ctx, "1.30", "config update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/container_attach.go b/vendor/github.com/docker/docker/client/container_attach.go index 2e7a13e5..6a32e5f6 100644 --- a/vendor/github.com/docker/docker/client/container_attach.go +++ b/vendor/github.com/docker/docker/client/container_attach.go @@ -33,12 +33,7 @@ import ( // // You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this // stream. -func (cli *Client) ContainerAttach(ctx context.Context, containerID string, options container.AttachOptions) (types.HijackedResponse, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return types.HijackedResponse{}, err - } - +func (cli *Client) ContainerAttach(ctx context.Context, container string, options container.AttachOptions) (types.HijackedResponse, error) { query := url.Values{} if options.Stream { query.Set("stream", "1") @@ -59,7 +54,7 @@ func (cli *Client) ContainerAttach(ctx context.Context, containerID string, opti query.Set("logs", "1") } - return cli.postHijacked(ctx, "/containers/"+containerID+"/attach", query, nil, http.Header{ + return cli.postHijacked(ctx, "/containers/"+container+"/attach", query, nil, http.Header{ "Content-Type": {"text/plain"}, }) } diff --git a/vendor/github.com/docker/docker/client/container_commit.go b/vendor/github.com/docker/docker/client/container_commit.go index 718465ce..26b3f091 100644 --- a/vendor/github.com/docker/docker/client/container_commit.go +++ b/vendor/github.com/docker/docker/client/container_commit.go @@ -12,12 +12,7 @@ import ( ) // ContainerCommit applies changes to a container and creates a new tagged image. -func (cli *Client) ContainerCommit(ctx context.Context, containerID string, options container.CommitOptions) (types.IDResponse, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return types.IDResponse{}, err - } - +func (cli *Client) ContainerCommit(ctx context.Context, container string, options container.CommitOptions) (types.IDResponse, error) { var repository, tag string if options.Reference != "" { ref, err := reference.ParseNormalizedNamed(options.Reference) @@ -37,7 +32,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti } query := url.Values{} - query.Set("container", containerID) + query.Set("container", container) query.Set("repo", repository) query.Set("tag", tag) query.Set("comment", options.Comment) diff --git a/vendor/github.com/docker/docker/client/container_copy.go b/vendor/github.com/docker/docker/client/container_copy.go index 3604a0ad..8490a3b1 100644 --- a/vendor/github.com/docker/docker/client/container_copy.go +++ b/vendor/github.com/docker/docker/client/container_copy.go @@ -16,15 +16,11 @@ import ( // ContainerStatPath returns stat information about a path inside the container filesystem. func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path string) (container.PathStat, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.PathStat{}, err - } - query := url.Values{} query.Set("path", filepath.ToSlash(path)) // Normalize the paths used in the API. - response, err := cli.head(ctx, "/containers/"+containerID+"/archive", query, nil) + urlStr := "/containers/" + containerID + "/archive" + response, err := cli.head(ctx, urlStr, query, nil) defer ensureReaderClosed(response) if err != nil { return container.PathStat{}, err @@ -35,11 +31,6 @@ func (cli *Client) ContainerStatPath(ctx context.Context, containerID, path stri // CopyToContainer copies content into the container filesystem. // Note that `content` must be a Reader for a TAR archive func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options container.CopyToContainerOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} query.Set("path", filepath.ToSlash(dstPath)) // Normalize the paths used in the API. // Do not allow for an existing directory to be overwritten by a non-directory and vice versa. @@ -51,7 +42,9 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str query.Set("copyUIDGID", "true") } - response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, content, nil) + apiPath := "/containers/" + containerID + "/archive" + + response, err := cli.putRaw(ctx, apiPath, query, content, nil) defer ensureReaderClosed(response) if err != nil { return err @@ -63,15 +56,11 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID, dstPath str // CopyFromContainer gets the content from the container and returns it as a Reader // for a TAR archive to manipulate it in the host. It's up to the caller to close the reader. func (cli *Client) CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return nil, container.PathStat{}, err - } - query := make(url.Values, 1) query.Set("path", filepath.ToSlash(srcPath)) // Normalize the paths used in the API. - response, err := cli.get(ctx, "/containers/"+containerID+"/archive", query, nil) + apiPath := "/containers/" + containerID + "/archive" + response, err := cli.get(ctx, apiPath, query, nil) if err != nil { return nil, container.PathStat{}, err } diff --git a/vendor/github.com/docker/docker/client/container_create.go b/vendor/github.com/docker/docker/client/container_create.go index 94925d7b..5442d426 100644 --- a/vendor/github.com/docker/docker/client/container_create.go +++ b/vendor/github.com/docker/docker/client/container_create.go @@ -5,8 +5,6 @@ import ( "encoding/json" "net/url" "path" - "sort" - "strings" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" @@ -14,6 +12,12 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) +type configWrapper struct { + *container.Config + HostConfig *container.HostConfig + NetworkingConfig *network.NetworkingConfig +} + // ContainerCreate creates a new container based on the given configuration. // 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 *ocispec.Platform, containerName string) (container.CreateResponse, error) { @@ -54,9 +58,6 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config // When using API under 1.42, the Linux daemon doesn't respect the ConsoleSize hostConfig.ConsoleSize = [2]uint{0, 0} } - - hostConfig.CapAdd = normalizeCapabilities(hostConfig.CapAdd) - hostConfig.CapDrop = normalizeCapabilities(hostConfig.CapDrop) } // Since API 1.44, the container-wide MacAddress is deprecated and will trigger a WARNING if it's specified. @@ -73,7 +74,7 @@ func (cli *Client) ContainerCreate(ctx context.Context, config *container.Config query.Set("name", containerName) } - body := container.CreateRequest{ + body := configWrapper{ Config: config, HostConfig: hostConfig, NetworkingConfig: networkingConfig, @@ -113,42 +114,3 @@ func hasEndpointSpecificMacAddress(networkingConfig *network.NetworkingConfig) b } return false } - -// allCapabilities is a magic value for "all capabilities" -const allCapabilities = "ALL" - -// normalizeCapabilities normalizes capabilities to their canonical form, -// removes duplicates, and sorts the results. -// -// It is similar to [github.com/docker/docker/oci/caps.NormalizeLegacyCapabilities], -// but performs no validation based on supported capabilities. -func normalizeCapabilities(caps []string) []string { - var normalized []string - - unique := make(map[string]struct{}) - for _, c := range caps { - c = normalizeCap(c) - if _, ok := unique[c]; ok { - continue - } - unique[c] = struct{}{} - normalized = append(normalized, c) - } - - sort.Strings(normalized) - return normalized -} - -// normalizeCap normalizes a capability to its canonical format by upper-casing -// and adding a "CAP_" prefix (if not yet present). It also accepts the "ALL" -// magic-value. -func normalizeCap(cap string) string { - cap = strings.ToUpper(cap) - if cap == allCapabilities { - return cap - } - if !strings.HasPrefix(cap, "CAP_") { - cap = "CAP_" + cap - } - return cap -} diff --git a/vendor/github.com/docker/docker/client/container_diff.go b/vendor/github.com/docker/docker/client/container_diff.go index 38e92dbf..c22c819a 100644 --- a/vendor/github.com/docker/docker/client/container_diff.go +++ b/vendor/github.com/docker/docker/client/container_diff.go @@ -10,21 +10,14 @@ import ( // ContainerDiff shows differences in a container filesystem since it was started. func (cli *Client) ContainerDiff(ctx context.Context, containerID string) ([]container.FilesystemChange, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return nil, err - } + var changes []container.FilesystemChange serverResp, err := cli.get(ctx, "/containers/"+containerID+"/changes", url.Values{}, nil) defer ensureReaderClosed(serverResp) if err != nil { - return nil, err + return changes, err } - var changes []container.FilesystemChange err = json.NewDecoder(serverResp.body).Decode(&changes) - if err != nil { - return nil, err - } return changes, err } diff --git a/vendor/github.com/docker/docker/client/container_exec.go b/vendor/github.com/docker/docker/client/container_exec.go index 4891b98e..9379448d 100644 --- a/vendor/github.com/docker/docker/client/container_exec.go +++ b/vendor/github.com/docker/docker/client/container_exec.go @@ -11,11 +11,8 @@ import ( ) // ContainerExecCreate creates a new exec configuration to run an exec process. -func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, options container.ExecOptions) (types.IDResponse, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return types.IDResponse{}, err - } +func (cli *Client) ContainerExecCreate(ctx context.Context, container string, options container.ExecOptions) (types.IDResponse, error) { + var response types.IDResponse // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. @@ -23,23 +20,21 @@ func (cli *Client) ContainerExecCreate(ctx context.Context, containerID string, // Normally, version-negotiation (if enabled) would not happen until // the API request is made. if err := cli.checkVersion(ctx); err != nil { - return types.IDResponse{}, err + return response, err } if err := cli.NewVersionError(ctx, "1.25", "env"); len(options.Env) != 0 && err != nil { - return types.IDResponse{}, err + return response, err } if versions.LessThan(cli.ClientVersion(), "1.42") { options.ConsoleSize = nil } - resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, options, nil) + resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, options, nil) defer ensureReaderClosed(resp) if err != nil { - return types.IDResponse{}, err + return response, err } - - var response types.IDResponse err = json.NewDecoder(resp.body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_export.go b/vendor/github.com/docker/docker/client/container_export.go index 1e45a992..d0c0a5cb 100644 --- a/vendor/github.com/docker/docker/client/container_export.go +++ b/vendor/github.com/docker/docker/client/container_export.go @@ -10,11 +10,6 @@ import ( // and returns them as an io.ReadCloser. It's up to the caller // to close the stream. func (cli *Client) ContainerExport(ctx context.Context, containerID string) (io.ReadCloser, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return nil, err - } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/export", url.Values{}, nil) if err != nil { return nil, err diff --git a/vendor/github.com/docker/docker/client/container_inspect.go b/vendor/github.com/docker/docker/client/container_inspect.go index 7fe86a2a..d48f0d3a 100644 --- a/vendor/github.com/docker/docker/client/container_inspect.go +++ b/vendor/github.com/docker/docker/client/container_inspect.go @@ -7,34 +7,30 @@ import ( "io" "net/url" - "github.com/docker/docker/api/types/container" + "github.com/docker/docker/api/types" ) // ContainerInspect returns the container information. -func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (container.InspectResponse, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.InspectResponse{}, err +func (cli *Client) ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error) { + if containerID == "" { + return types.ContainerJSON{}, objectNotFoundError{object: "container", id: containerID} } - serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return container.InspectResponse{}, err + return types.ContainerJSON{}, err } - var response container.InspectResponse + var response types.ContainerJSON err = json.NewDecoder(serverResp.body).Decode(&response) return response, err } // ContainerInspectWithRaw returns the container information and its raw representation. -func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (container.InspectResponse, []byte, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.InspectResponse{}, nil, err +func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID string, getSize bool) (types.ContainerJSON, []byte, error) { + if containerID == "" { + return types.ContainerJSON{}, nil, objectNotFoundError{object: "container", id: containerID} } - query := url.Values{} if getSize { query.Set("size", "1") @@ -42,15 +38,15 @@ func (cli *Client) ContainerInspectWithRaw(ctx context.Context, containerID stri serverResp, err := cli.get(ctx, "/containers/"+containerID+"/json", query, nil) defer ensureReaderClosed(serverResp) if err != nil { - return container.InspectResponse{}, nil, err + return types.ContainerJSON{}, nil, err } body, err := io.ReadAll(serverResp.body) if err != nil { - return container.InspectResponse{}, nil, err + return types.ContainerJSON{}, nil, err } - var response container.InspectResponse + var response types.ContainerJSON rdr := bytes.NewReader(body) err = json.NewDecoder(rdr).Decode(&response) return response, body, err diff --git a/vendor/github.com/docker/docker/client/container_kill.go b/vendor/github.com/docker/docker/client/container_kill.go index 22767ae6..7c9529f1 100644 --- a/vendor/github.com/docker/docker/client/container_kill.go +++ b/vendor/github.com/docker/docker/client/container_kill.go @@ -7,11 +7,6 @@ import ( // ContainerKill terminates the container process but does not remove the container from the docker host. func (cli *Client) ContainerKill(ctx context.Context, containerID, signal string) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if signal != "" { query.Set("signal", signal) diff --git a/vendor/github.com/docker/docker/client/container_list.go b/vendor/github.com/docker/docker/client/container_list.go index 46c6950c..782e1b3c 100644 --- a/vendor/github.com/docker/docker/client/container_list.go +++ b/vendor/github.com/docker/docker/client/container_list.go @@ -6,12 +6,13 @@ import ( "net/url" "strconv" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" ) // ContainerList returns the list of containers in the docker host. -func (cli *Client) ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) { +func (cli *Client) ContainerList(ctx context.Context, options container.ListOptions) ([]types.Container, error) { query := url.Values{} if options.All { @@ -50,7 +51,7 @@ func (cli *Client) ContainerList(ctx context.Context, options container.ListOpti return nil, err } - var containers []container.Summary + var containers []types.Container err = json.NewDecoder(resp.body).Decode(&containers) return containers, err } diff --git a/vendor/github.com/docker/docker/client/container_logs.go b/vendor/github.com/docker/docker/client/container_logs.go index 989a66a9..61197d84 100644 --- a/vendor/github.com/docker/docker/client/container_logs.go +++ b/vendor/github.com/docker/docker/client/container_logs.go @@ -33,12 +33,7 @@ import ( // // You can use github.com/docker/docker/pkg/stdcopy.StdCopy to demultiplex this // stream. -func (cli *Client) ContainerLogs(ctx context.Context, containerID string, options container.LogsOptions) (io.ReadCloser, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return nil, err - } - +func (cli *Client) ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error) { query := url.Values{} if options.ShowStdout { query.Set("stdout", "1") @@ -77,7 +72,7 @@ func (cli *Client) ContainerLogs(ctx context.Context, containerID string, option } query.Set("tail", options.Tail) - resp, err := cli.get(ctx, "/containers/"+containerID+"/logs", query, nil) + resp, err := cli.get(ctx, "/containers/"+container+"/logs", query, nil) if err != nil { return nil, err } diff --git a/vendor/github.com/docker/docker/client/container_pause.go b/vendor/github.com/docker/docker/client/container_pause.go index 5cc29840..5e7271a3 100644 --- a/vendor/github.com/docker/docker/client/container_pause.go +++ b/vendor/github.com/docker/docker/client/container_pause.go @@ -4,11 +4,6 @@ import "context" // ContainerPause pauses the main process of a given container without terminating it. func (cli *Client) ContainerPause(ctx context.Context, containerID string) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/pause", nil, nil, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/container_prune.go b/vendor/github.com/docker/docker/client/container_prune.go index ce38ad9b..29c922da 100644 --- a/vendor/github.com/docker/docker/client/container_prune.go +++ b/vendor/github.com/docker/docker/client/container_prune.go @@ -11,24 +11,25 @@ import ( // ContainersPrune requests the daemon to delete unused data func (cli *Client) ContainersPrune(ctx context.Context, pruneFilters filters.Args) (container.PruneReport, error) { + var report container.PruneReport + if err := cli.NewVersionError(ctx, "1.25", "container prune"); err != nil { - return container.PruneReport{}, err + return report, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return container.PruneReport{}, err + return report, err } serverResp, err := cli.post(ctx, "/containers/prune", query, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return container.PruneReport{}, err + return report, err } - var report container.PruneReport if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return container.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err) + return report, fmt.Errorf("Error retrieving disk usage: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/container_remove.go b/vendor/github.com/docker/docker/client/container_remove.go index 6661351a..39f7b106 100644 --- a/vendor/github.com/docker/docker/client/container_remove.go +++ b/vendor/github.com/docker/docker/client/container_remove.go @@ -9,11 +9,6 @@ import ( // ContainerRemove kills and removes a container from the docker host. func (cli *Client) ContainerRemove(ctx context.Context, containerID string, options container.RemoveOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if options.RemoveVolumes { query.Set("v", "1") diff --git a/vendor/github.com/docker/docker/client/container_rename.go b/vendor/github.com/docker/docker/client/container_rename.go index 0a092310..240fdf55 100644 --- a/vendor/github.com/docker/docker/client/container_rename.go +++ b/vendor/github.com/docker/docker/client/container_rename.go @@ -7,11 +7,6 @@ import ( // ContainerRename changes the name of a given container. func (cli *Client) ContainerRename(ctx context.Context, containerID, newContainerName string) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} query.Set("name", newContainerName) resp, err := cli.post(ctx, "/containers/"+containerID+"/rename", query, nil, nil) diff --git a/vendor/github.com/docker/docker/client/container_resize.go b/vendor/github.com/docker/docker/client/container_resize.go index 725c08ad..5cfd01d4 100644 --- a/vendor/github.com/docker/docker/client/container_resize.go +++ b/vendor/github.com/docker/docker/client/container_resize.go @@ -10,27 +10,18 @@ import ( // ContainerResize changes the size of the tty for a container. func (cli *Client) ContainerResize(ctx context.Context, containerID string, options container.ResizeOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } return cli.resize(ctx, "/containers/"+containerID, options.Height, options.Width) } // ContainerExecResize changes the size of the tty for an exec process running inside a container. func (cli *Client) ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error { - execID, err := trimID("exec", execID) - if err != nil { - return err - } return cli.resize(ctx, "/exec/"+execID, options.Height, options.Width) } func (cli *Client) resize(ctx context.Context, basePath string, height, width uint) error { - // FIXME(thaJeztah): the API / backend accepts uint32, but container.ResizeOptions uses uint. query := url.Values{} - query.Set("h", strconv.FormatUint(uint64(height), 10)) - query.Set("w", strconv.FormatUint(uint64(width), 10)) + query.Set("h", strconv.Itoa(int(height))) + query.Set("w", strconv.Itoa(int(width))) resp, err := cli.post(ctx, basePath+"/resize", query, nil, nil) ensureReaderClosed(resp) diff --git a/vendor/github.com/docker/docker/client/container_restart.go b/vendor/github.com/docker/docker/client/container_restart.go index 50559ba6..02b5079b 100644 --- a/vendor/github.com/docker/docker/client/container_restart.go +++ b/vendor/github.com/docker/docker/client/container_restart.go @@ -13,11 +13,6 @@ import ( // It makes the daemon wait for the container to be up again for // a specific amount of time, given the timeout. func (cli *Client) ContainerRestart(ctx context.Context, containerID string, options container.StopOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if options.Timeout != nil { query.Set("t", strconv.Itoa(*options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/container_start.go b/vendor/github.com/docker/docker/client/container_start.go index b81ed3eb..33ba85f2 100644 --- a/vendor/github.com/docker/docker/client/container_start.go +++ b/vendor/github.com/docker/docker/client/container_start.go @@ -9,11 +9,6 @@ import ( // ContainerStart sends a request to the docker daemon to start a container. func (cli *Client) ContainerStart(ctx context.Context, containerID string, options container.StartOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if len(options.CheckpointID) != 0 { query.Set("checkpoint", options.CheckpointID) diff --git a/vendor/github.com/docker/docker/client/container_stats.go b/vendor/github.com/docker/docker/client/container_stats.go index f90d1c9a..b5641dae 100644 --- a/vendor/github.com/docker/docker/client/container_stats.go +++ b/vendor/github.com/docker/docker/client/container_stats.go @@ -10,11 +10,6 @@ import ( // ContainerStats returns near realtime stats for a given container. // It's up to the caller to close the io.ReadCloser returned. func (cli *Client) ContainerStats(ctx context.Context, containerID string, stream bool) (container.StatsResponseReader, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.StatsResponseReader{}, err - } - query := url.Values{} query.Set("stream", "0") if stream { @@ -35,11 +30,6 @@ func (cli *Client) ContainerStats(ctx context.Context, containerID string, strea // ContainerStatsOneShot gets a single stat entry from a container. // It differs from `ContainerStats` in that the API should not wait to prime the stats func (cli *Client) ContainerStatsOneShot(ctx context.Context, containerID string) (container.StatsResponseReader, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.StatsResponseReader{}, err - } - query := url.Values{} query.Set("stream", "0") query.Set("one-shot", "1") diff --git a/vendor/github.com/docker/docker/client/container_stop.go b/vendor/github.com/docker/docker/client/container_stop.go index eb0129ce..7c98a354 100644 --- a/vendor/github.com/docker/docker/client/container_stop.go +++ b/vendor/github.com/docker/docker/client/container_stop.go @@ -17,11 +17,6 @@ import ( // otherwise the engine default. A negative timeout value can be specified, // meaning no timeout, i.e. no forceful termination is performed. func (cli *Client) ContainerStop(ctx context.Context, containerID string, options container.StopOptions) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - query := url.Values{} if options.Timeout != nil { query.Set("t", strconv.Itoa(*options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/container_top.go b/vendor/github.com/docker/docker/client/container_top.go index 4eac031f..a5b78999 100644 --- a/vendor/github.com/docker/docker/client/container_top.go +++ b/vendor/github.com/docker/docker/client/container_top.go @@ -11,11 +11,7 @@ import ( // ContainerTop shows process information from within a container. func (cli *Client) ContainerTop(ctx context.Context, containerID string, arguments []string) (container.ContainerTopOKBody, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.ContainerTopOKBody{}, err - } - + var response container.ContainerTopOKBody query := url.Values{} if len(arguments) > 0 { query.Set("ps_args", strings.Join(arguments, " ")) @@ -24,10 +20,9 @@ func (cli *Client) ContainerTop(ctx context.Context, containerID string, argumen resp, err := cli.get(ctx, "/containers/"+containerID+"/top", query, nil) defer ensureReaderClosed(resp) if err != nil { - return container.ContainerTopOKBody{}, err + return response, err } - var response container.ContainerTopOKBody err = json.NewDecoder(resp.body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_unpause.go b/vendor/github.com/docker/docker/client/container_unpause.go index f602549b..1d8f8731 100644 --- a/vendor/github.com/docker/docker/client/container_unpause.go +++ b/vendor/github.com/docker/docker/client/container_unpause.go @@ -4,11 +4,6 @@ import "context" // ContainerUnpause resumes the process execution within a container func (cli *Client) ContainerUnpause(ctx context.Context, containerID string) error { - containerID, err := trimID("container", containerID) - if err != nil { - return err - } - resp, err := cli.post(ctx, "/containers/"+containerID+"/unpause", nil, nil, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/container_update.go b/vendor/github.com/docker/docker/client/container_update.go index d14b14af..bf68a530 100644 --- a/vendor/github.com/docker/docker/client/container_update.go +++ b/vendor/github.com/docker/docker/client/container_update.go @@ -9,18 +9,13 @@ import ( // ContainerUpdate updates the resources of a container. func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, updateConfig container.UpdateConfig) (container.ContainerUpdateOKBody, error) { - containerID, err := trimID("container", containerID) - if err != nil { - return container.ContainerUpdateOKBody{}, err - } - + var response container.ContainerUpdateOKBody serverResp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil) defer ensureReaderClosed(serverResp) if err != nil { - return container.ContainerUpdateOKBody{}, err + return response, err } - var response container.ContainerUpdateOKBody err = json.NewDecoder(serverResp.body).Decode(&response) return response, err } diff --git a/vendor/github.com/docker/docker/client/container_wait.go b/vendor/github.com/docker/docker/client/container_wait.go index fd025d25..8bb6be0a 100644 --- a/vendor/github.com/docker/docker/client/container_wait.go +++ b/vendor/github.com/docker/docker/client/container_wait.go @@ -33,12 +33,6 @@ func (cli *Client) ContainerWait(ctx context.Context, containerID string, condit resultC := make(chan container.WaitResponse) errC := make(chan error, 1) - containerID, err := trimID("container", containerID) - if err != nil { - errC <- err - return resultC, errC - } - // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. // diff --git a/vendor/github.com/docker/docker/client/errors.go b/vendor/github.com/docker/docker/client/errors.go index 609f92ce..0d01e243 100644 --- a/vendor/github.com/docker/docker/client/errors.go +++ b/vendor/github.com/docker/docker/client/errors.go @@ -2,11 +2,11 @@ package client // import "github.com/docker/docker/client" import ( "context" - "errors" "fmt" "github.com/docker/docker/api/types/versions" "github.com/docker/docker/errdefs" + "github.com/pkg/errors" ) // errConnectionFailed implements an error returned when connection failed. @@ -29,18 +29,10 @@ func IsErrConnectionFailed(err error) bool { } // ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed. -// -// Deprecated: this function was only used internally, and will be removed in the next release. func ErrorConnectionFailed(host string) error { - return connectionFailed(host) -} - -// connectionFailed returns an error with host in the error message when connection -// to docker daemon failed. -func connectionFailed(host string) error { var err error if host == "" { - err = errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") + err = fmt.Errorf("Cannot connect to the Docker daemon. Is the docker daemon running on this host?") } else { err = fmt.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host) } diff --git a/vendor/github.com/docker/docker/client/hijack.go b/vendor/github.com/docker/docker/client/hijack.go index 2c78fad0..839d4c5c 100644 --- a/vendor/github.com/docker/docker/client/hijack.go +++ b/vendor/github.com/docker/docker/client/hijack.go @@ -25,17 +25,12 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu if err != nil { return types.HijackedResponse{}, err } - conn, mediaType, err := setupHijackConn(cli.dialer(), req, "tcp") + conn, mediaType, err := cli.setupHijackConn(req, "tcp") if err != nil { return types.HijackedResponse{}, err } - if versions.LessThan(cli.ClientVersion(), "1.42") { - // Prior to 1.42, Content-Type is always set to raw-stream and not relevant - mediaType = "" - } - - return types.NewHijackedResponse(conn, mediaType), nil + return types.NewHijackedResponse(conn, mediaType), err } // DialHijack returns a hijacked connection with negotiated protocol proto. @@ -46,15 +41,16 @@ func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[s } req = cli.addHeaders(req, meta) - conn, _, err := setupHijackConn(cli.Dialer(), req, proto) + conn, _, err := cli.setupHijackConn(req, proto) return conn, err } -func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { +func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, _ string, retErr error) { ctx := req.Context() req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", proto) + dialer := cli.Dialer() conn, err := dialer(ctx) if err != nil { return nil, "", errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?") @@ -100,7 +96,13 @@ func setupHijackConn(dialer func(context.Context) (net.Conn, error), req *http.R hc.r.Reset(nil) } - return conn, resp.Header.Get("Content-Type"), nil + var mediaType string + if versions.GreaterThanOrEqualTo(cli.ClientVersion(), "1.42") { + // Prior to 1.42, Content-Type is always set to raw-stream and not relevant + mediaType = resp.Header.Get("Content-Type") + } + + return conn, mediaType, nil } // hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case diff --git a/vendor/github.com/docker/docker/client/image_build.go b/vendor/github.com/docker/docker/client/image_build.go index 62037c7f..d294ddc8 100644 --- a/vendor/github.com/docker/docker/client/image_build.go +++ b/vendor/github.com/docker/docker/client/image_build.go @@ -12,7 +12,6 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/network" ) // ImageBuild sends a request to the daemon to build images. @@ -45,15 +44,10 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio } func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) { - query := url.Values{} - if len(options.Tags) > 0 { - query["t"] = options.Tags - } - if len(options.SecurityOpt) > 0 { - query["securityopt"] = options.SecurityOpt - } - if len(options.ExtraHosts) > 0 { - query["extrahosts"] = options.ExtraHosts + query := url.Values{ + "t": options.Tags, + "securityopt": options.SecurityOpt, + "extrahosts": options.ExtraHosts, } if options.SuppressOutput { query.Set("q", "1") @@ -64,11 +58,9 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I if options.NoCache { query.Set("nocache", "1") } - if !options.Remove { - // only send value when opting out because the daemon's default is - // to remove intermediate containers after a successful build, - // - // TODO(thaJeztah): deprecate "Remove" option, and provide a "NoRemove" or "Keep" option instead. + if options.Remove { + query.Set("rm", "1") + } else { query.Set("rm", "0") } @@ -91,70 +83,42 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I query.Set("isolation", string(options.Isolation)) } - if options.CPUSetCPUs != "" { - query.Set("cpusetcpus", options.CPUSetCPUs) + query.Set("cpusetcpus", options.CPUSetCPUs) + query.Set("networkmode", options.NetworkMode) + query.Set("cpusetmems", options.CPUSetMems) + query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10)) + query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10)) + query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10)) + query.Set("memory", strconv.FormatInt(options.Memory, 10)) + query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10)) + query.Set("cgroupparent", options.CgroupParent) + query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10)) + query.Set("dockerfile", options.Dockerfile) + query.Set("target", options.Target) + + ulimitsJSON, err := json.Marshal(options.Ulimits) + if err != nil { + return query, err } - if options.NetworkMode != "" && options.NetworkMode != network.NetworkDefault { - query.Set("networkmode", options.NetworkMode) + query.Set("ulimits", string(ulimitsJSON)) + + buildArgsJSON, err := json.Marshal(options.BuildArgs) + if err != nil { + return query, err } - if options.CPUSetMems != "" { - query.Set("cpusetmems", options.CPUSetMems) + query.Set("buildargs", string(buildArgsJSON)) + + labelsJSON, err := json.Marshal(options.Labels) + if err != nil { + return query, err } - if options.CPUShares != 0 { - query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10)) - } - if options.CPUQuota != 0 { - query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10)) - } - if options.CPUPeriod != 0 { - query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10)) - } - if options.Memory != 0 { - query.Set("memory", strconv.FormatInt(options.Memory, 10)) - } - if options.MemorySwap != 0 { - query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10)) - } - if options.CgroupParent != "" { - query.Set("cgroupparent", options.CgroupParent) - } - if options.ShmSize != 0 { - query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10)) - } - if options.Dockerfile != "" { - query.Set("dockerfile", options.Dockerfile) - } - if options.Target != "" { - query.Set("target", options.Target) - } - if len(options.Ulimits) != 0 { - ulimitsJSON, err := json.Marshal(options.Ulimits) - if err != nil { - return query, err - } - query.Set("ulimits", string(ulimitsJSON)) - } - if len(options.BuildArgs) != 0 { - buildArgsJSON, err := json.Marshal(options.BuildArgs) - if err != nil { - return query, err - } - query.Set("buildargs", string(buildArgsJSON)) - } - if len(options.Labels) != 0 { - labelsJSON, err := json.Marshal(options.Labels) - if err != nil { - return query, err - } - query.Set("labels", string(labelsJSON)) - } - if len(options.CacheFrom) != 0 { - cacheFromJSON, err := json.Marshal(options.CacheFrom) - if err != nil { - return query, err - } - query.Set("cachefrom", string(cacheFromJSON)) + query.Set("labels", string(labelsJSON)) + + cacheFromJSON, err := json.Marshal(options.CacheFrom) + if err != nil { + return query, err } + query.Set("cachefrom", string(cacheFromJSON)) if options.SessionID != "" { query.Set("session", options.SessionID) } @@ -167,9 +131,7 @@ func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.I if options.BuildID != "" { query.Set("buildid", options.BuildID) } - if options.Version != "" { - query.Set("version", string(options.Version)) - } + query.Set("version", string(options.Version)) if options.Outputs != nil { outputsJSON, err := json.Marshal(options.Outputs) diff --git a/vendor/github.com/docker/docker/client/image_history.go b/vendor/github.com/docker/docker/client/image_history.go index 747a569b..b5bea10d 100644 --- a/vendor/github.com/docker/docker/client/image_history.go +++ b/vendor/github.com/docker/docker/client/image_history.go @@ -9,27 +9,14 @@ import ( ) // ImageHistory returns the changes in an image in history format. -func (cli *Client) ImageHistory(ctx context.Context, imageID string, opts image.HistoryOptions) ([]image.HistoryResponseItem, error) { - query := url.Values{} - if opts.Platform != nil { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { - return nil, err - } - - p, err := encodePlatform(opts.Platform) - if err != nil { - return nil, err - } - query.Set("platform", p) - } - - serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", query, nil) +func (cli *Client) ImageHistory(ctx context.Context, imageID string) ([]image.HistoryResponseItem, error) { + var history []image.HistoryResponseItem + serverResp, err := cli.get(ctx, "/images/"+imageID+"/history", url.Values{}, nil) defer ensureReaderClosed(serverResp) if err != nil { - return nil, err + return history, err } - var history []image.HistoryResponseItem err = json.NewDecoder(serverResp.body).Decode(&history) return history, err } diff --git a/vendor/github.com/docker/docker/client/image_import.go b/vendor/github.com/docker/docker/client/image_import.go index dea36268..43d55eda 100644 --- a/vendor/github.com/docker/docker/client/image_import.go +++ b/vendor/github.com/docker/docker/client/image_import.go @@ -21,18 +21,10 @@ func (cli *Client) ImageImport(ctx context.Context, source image.ImportSource, r } query := url.Values{} - if source.SourceName != "" { - query.Set("fromSrc", source.SourceName) - } - if ref != "" { - query.Set("repo", ref) - } - if options.Tag != "" { - query.Set("tag", options.Tag) - } - if options.Message != "" { - query.Set("message", options.Message) - } + query.Set("fromSrc", source.SourceName) + query.Set("repo", ref) + query.Set("tag", options.Tag) + query.Set("message", options.Message) if options.Platform != "" { query.Set("platform", strings.ToLower(options.Platform)) } diff --git a/vendor/github.com/docker/docker/client/image_inspect.go b/vendor/github.com/docker/docker/client/image_inspect.go index fb23c310..1de10e5a 100644 --- a/vendor/github.com/docker/docker/client/image_inspect.go +++ b/vendor/github.com/docker/docker/client/image_inspect.go @@ -4,106 +4,29 @@ import ( "bytes" "context" "encoding/json" - "fmt" "io" - "net/url" - "github.com/docker/docker/api/types/image" + "github.com/docker/docker/api/types" ) -// ImageInspectOption is a type representing functional options for the image inspect operation. -type ImageInspectOption interface { - Apply(*imageInspectOpts) error -} -type imageInspectOptionFunc func(opt *imageInspectOpts) error - -func (f imageInspectOptionFunc) Apply(o *imageInspectOpts) error { - return f(o) -} - -// ImageInspectWithRawResponse instructs the client to additionally store the -// raw inspect response in the provided buffer. -func ImageInspectWithRawResponse(raw *bytes.Buffer) ImageInspectOption { - return imageInspectOptionFunc(func(opts *imageInspectOpts) error { - opts.raw = raw - return nil - }) -} - -// ImageInspectWithManifests sets manifests API option for the image inspect operation. -// This option is only available for API version 1.48 and up. -// With this option set, the image inspect operation response will have the -// [image.InspectResponse.Manifests] field populated if the server is multi-platform capable. -func ImageInspectWithManifests(manifests bool) ImageInspectOption { - return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error { - clientOpts.apiOptions.Manifests = manifests - return nil - }) -} - -// ImageInspectWithAPIOpts sets the API options for the image inspect operation. -func ImageInspectWithAPIOpts(opts image.InspectOptions) ImageInspectOption { - return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error { - clientOpts.apiOptions = opts - return nil - }) -} - -type imageInspectOpts struct { - raw *bytes.Buffer - apiOptions image.InspectOptions -} - -// ImageInspect returns the image information. -func (cli *Client) ImageInspect(ctx context.Context, imageID string, inspectOpts ...ImageInspectOption) (image.InspectResponse, error) { +// ImageInspectWithRaw returns the image information and its raw representation. +func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (types.ImageInspect, []byte, error) { if imageID == "" { - return image.InspectResponse{}, objectNotFoundError{object: "image", id: imageID} + return types.ImageInspect{}, nil, objectNotFoundError{object: "image", id: imageID} } - - var opts imageInspectOpts - for _, opt := range inspectOpts { - if err := opt.Apply(&opts); err != nil { - return image.InspectResponse{}, fmt.Errorf("error applying image inspect option: %w", err) - } - } - - query := url.Values{} - if opts.apiOptions.Manifests { - if err := cli.NewVersionError(ctx, "1.48", "manifests"); err != nil { - return image.InspectResponse{}, err - } - query.Set("manifests", "1") - } - - serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil) + serverResp, err := cli.get(ctx, "/images/"+imageID+"/json", nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return image.InspectResponse{}, err + return types.ImageInspect{}, nil, err } - buf := opts.raw - if buf == nil { - buf = &bytes.Buffer{} - } - - if _, err := io.Copy(buf, serverResp.body); err != nil { - return image.InspectResponse{}, err - } - - var response image.InspectResponse - err = json.Unmarshal(buf.Bytes(), &response) - return response, err -} - -// ImageInspectWithRaw returns the image information and its raw representation. -// -// Deprecated: Use [Client.ImageInspect] instead. -// Raw response can be obtained by [ImageInspectWithRawResponse] option. -func (cli *Client) ImageInspectWithRaw(ctx context.Context, imageID string) (image.InspectResponse, []byte, error) { - var buf bytes.Buffer - resp, err := cli.ImageInspect(ctx, imageID, ImageInspectWithRawResponse(&buf)) + body, err := io.ReadAll(serverResp.body) if err != nil { - return image.InspectResponse{}, nil, err + return types.ImageInspect{}, nil, err } - return resp, buf.Bytes(), err + + var response types.ImageInspect + rdr := bytes.NewReader(body) + err = json.NewDecoder(rdr).Decode(&response) + return response, body, err } diff --git a/vendor/github.com/docker/docker/client/image_load.go b/vendor/github.com/docker/docker/client/image_load.go index 50cce4fd..c68f0013 100644 --- a/vendor/github.com/docker/docker/client/image_load.go +++ b/vendor/github.com/docker/docker/client/image_load.go @@ -12,29 +12,13 @@ import ( // ImageLoad loads an image in the docker host from the client host. // It's up to the caller to close the io.ReadCloser in the // ImageLoadResponse returned by this function. -// -// Platform is an optional parameter that specifies the platform to load from -// the provided multi-platform image. This is only has effect if the input image -// is a multi-platform image. -func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, opts image.LoadOptions) (image.LoadResponse, error) { - query := url.Values{} - query.Set("quiet", "0") - if opts.Quiet { - query.Set("quiet", "1") +func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) { + v := url.Values{} + v.Set("quiet", "0") + if quiet { + v.Set("quiet", "1") } - if len(opts.Platforms) > 0 { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { - return image.LoadResponse{}, err - } - - p, err := encodePlatforms(opts.Platforms...) - if err != nil { - return image.LoadResponse{}, err - } - query["platform"] = p - } - - resp, err := cli.postRaw(ctx, "/images/load", query, input, http.Header{ + resp, err := cli.postRaw(ctx, "/images/load", v, input, http.Header{ "Content-Type": {"application/x-tar"}, }) if err != nil { diff --git a/vendor/github.com/docker/docker/client/image_prune.go b/vendor/github.com/docker/docker/client/image_prune.go index c731f193..5ee987e2 100644 --- a/vendor/github.com/docker/docker/client/image_prune.go +++ b/vendor/github.com/docker/docker/client/image_prune.go @@ -11,24 +11,25 @@ import ( // ImagesPrune requests the daemon to delete unused data func (cli *Client) ImagesPrune(ctx context.Context, pruneFilters filters.Args) (image.PruneReport, error) { + var report image.PruneReport + if err := cli.NewVersionError(ctx, "1.25", "image prune"); err != nil { - return image.PruneReport{}, err + return report, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return image.PruneReport{}, err + return report, err } serverResp, err := cli.post(ctx, "/images/prune", query, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return image.PruneReport{}, err + return report, err } - var report image.PruneReport if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return image.PruneReport{}, fmt.Errorf("Error retrieving disk usage: %v", err) + return report, fmt.Errorf("Error retrieving disk usage: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/image_save.go b/vendor/github.com/docker/docker/client/image_save.go index 1b378c32..d1314e4b 100644 --- a/vendor/github.com/docker/docker/client/image_save.go +++ b/vendor/github.com/docker/docker/client/image_save.go @@ -4,28 +4,15 @@ import ( "context" "io" "net/url" - - "github.com/docker/docker/api/types/image" ) // ImageSave retrieves one or more images from the docker host as an io.ReadCloser. // It's up to the caller to store the images and close the stream. -func (cli *Client) ImageSave(ctx context.Context, imageIDs []string, opts image.SaveOptions) (io.ReadCloser, error) { +func (cli *Client) ImageSave(ctx context.Context, imageIDs []string) (io.ReadCloser, error) { query := url.Values{ "names": imageIDs, } - if len(opts.Platforms) > 0 { - if err := cli.NewVersionError(ctx, "1.48", "platform"); err != nil { - return nil, err - } - p, err := encodePlatforms(opts.Platforms...) - if err != nil { - return nil, err - } - query["platform"] = p - } - resp, err := cli.get(ctx, "/images/get", query, nil) if err != nil { return nil, err diff --git a/vendor/github.com/docker/docker/client/client_interfaces.go b/vendor/github.com/docker/docker/client/interface.go similarity index 89% rename from vendor/github.com/docker/docker/client/client_interfaces.go rename to vendor/github.com/docker/docker/client/interface.go index 719177cb..cc60a5d1 100644 --- a/vendor/github.com/docker/docker/client/client_interfaces.go +++ b/vendor/github.com/docker/docker/client/interface.go @@ -20,23 +20,17 @@ import ( ) // CommonAPIClient is the common methods between stable and experimental versions of APIClient. -// -// Deprecated: use [APIClient] instead. This type will be an alias for [APIClient] in the next release, and removed after. -type CommonAPIClient = stableAPIClient - -// APIClient is an interface that clients that talk with a docker server must implement. -type APIClient interface { - stableAPIClient - CheckpointAPIClient // CheckpointAPIClient is still experimental. -} - -type stableAPIClient interface { +type CommonAPIClient interface { ConfigAPIClient ContainerAPIClient DistributionAPIClient ImageAPIClient + NodeAPIClient NetworkAPIClient PluginAPIClient + ServiceAPIClient + SwarmAPIClient + SecretAPIClient SystemAPIClient VolumeAPIClient ClientVersion() string @@ -45,25 +39,9 @@ type stableAPIClient interface { ServerVersion(ctx context.Context) (types.Version, error) NegotiateAPIVersion(ctx context.Context) NegotiateAPIVersionPing(types.Ping) - HijackDialer + DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) Dialer() func(context.Context) (net.Conn, error) Close() error - SwarmManagementAPIClient -} - -// SwarmManagementAPIClient defines all methods for managing Swarm-specific -// objects. -type SwarmManagementAPIClient interface { - SwarmAPIClient - NodeAPIClient - ServiceAPIClient - SecretAPIClient - ConfigAPIClient -} - -// HijackDialer defines methods for a hijack dialer. -type HijackDialer interface { - DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) } // ContainerAPIClient defines API client methods for the containers @@ -78,10 +56,10 @@ type ContainerAPIClient interface { ContainerExecResize(ctx context.Context, execID string, options container.ResizeOptions) error ContainerExecStart(ctx context.Context, execID string, options container.ExecStartOptions) error ContainerExport(ctx context.Context, container string) (io.ReadCloser, error) - ContainerInspect(ctx context.Context, container string) (container.InspectResponse, error) - ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (container.InspectResponse, []byte, error) + ContainerInspect(ctx context.Context, container string) (types.ContainerJSON, error) + ContainerInspectWithRaw(ctx context.Context, container string, getSize bool) (types.ContainerJSON, []byte, error) ContainerKill(ctx context.Context, container, signal string) error - ContainerList(ctx context.Context, options container.ListOptions) ([]container.Summary, error) + ContainerList(ctx context.Context, options container.ListOptions) ([]types.Container, error) ContainerLogs(ctx context.Context, container string, options container.LogsOptions) (io.ReadCloser, error) ContainerPause(ctx context.Context, container string) error ContainerRemove(ctx context.Context, container string, options container.RemoveOptions) error @@ -113,19 +91,16 @@ type ImageAPIClient interface { BuildCachePrune(ctx context.Context, opts types.BuildCachePruneOptions) (*types.BuildCachePruneReport, error) BuildCancel(ctx context.Context, id string) error ImageCreate(ctx context.Context, parentReference string, options image.CreateOptions) (io.ReadCloser, error) - ImageHistory(ctx context.Context, image string, opts image.HistoryOptions) ([]image.HistoryResponseItem, error) + ImageHistory(ctx context.Context, image string) ([]image.HistoryResponseItem, error) ImageImport(ctx context.Context, source image.ImportSource, ref string, options image.ImportOptions) (io.ReadCloser, error) - // Deprecated: Use [Client.ImageInspect] instead. - // Raw response can be obtained by [ImageInspectWithRawResponse] option. - ImageInspectWithRaw(ctx context.Context, image string) (image.InspectResponse, []byte, error) - ImageInspect(ctx context.Context, image string, _ ...ImageInspectOption) (image.InspectResponse, error) + ImageInspectWithRaw(ctx context.Context, image string) (types.ImageInspect, []byte, error) ImageList(ctx context.Context, options image.ListOptions) ([]image.Summary, error) - ImageLoad(ctx context.Context, input io.Reader, opts image.LoadOptions) (image.LoadResponse, error) + ImageLoad(ctx context.Context, input io.Reader, quiet bool) (image.LoadResponse, error) ImagePull(ctx context.Context, ref string, options image.PullOptions) (io.ReadCloser, error) ImagePush(ctx context.Context, ref string, options image.PushOptions) (io.ReadCloser, error) ImageRemove(ctx context.Context, image string, options image.RemoveOptions) ([]image.DeleteResponse, error) - ImageSave(ctx context.Context, images []string, opts image.SaveOptions) (io.ReadCloser, error) ImageSearch(ctx context.Context, term string, options registry.SearchOptions) ([]registry.SearchResult, error) + ImageSave(ctx context.Context, images []string) (io.ReadCloser, error) ImageTag(ctx context.Context, image, ref string) error ImagesPrune(ctx context.Context, pruneFilter filters.Args) (image.PruneReport, error) } diff --git a/vendor/github.com/docker/docker/client/checkpoint.go b/vendor/github.com/docker/docker/client/interface_experimental.go similarity index 76% rename from vendor/github.com/docker/docker/client/checkpoint.go rename to vendor/github.com/docker/docker/client/interface_experimental.go index f690f7c9..c585c104 100644 --- a/vendor/github.com/docker/docker/client/checkpoint.go +++ b/vendor/github.com/docker/docker/client/interface_experimental.go @@ -6,11 +6,11 @@ import ( "github.com/docker/docker/api/types/checkpoint" ) -// CheckpointAPIClient defines API client methods for the checkpoints. -// -// Experimental: checkpoint and restore is still an experimental feature, -// and only available if the daemon is running with experimental features -// enabled. +type apiClientExperimental interface { + CheckpointAPIClient +} + +// CheckpointAPIClient defines API client methods for the checkpoints type CheckpointAPIClient interface { CheckpointCreate(ctx context.Context, container string, options checkpoint.CreateOptions) error CheckpointDelete(ctx context.Context, container string, options checkpoint.DeleteOptions) error diff --git a/vendor/github.com/docker/docker/client/interface_stable.go b/vendor/github.com/docker/docker/client/interface_stable.go new file mode 100644 index 00000000..5502cd74 --- /dev/null +++ b/vendor/github.com/docker/docker/client/interface_stable.go @@ -0,0 +1,10 @@ +package client // import "github.com/docker/docker/client" + +// APIClient is an interface that clients that talk with a docker server must implement. +type APIClient interface { + CommonAPIClient + apiClientExperimental +} + +// Ensure that Client always implements APIClient. +var _ APIClient = &Client{} diff --git a/vendor/github.com/docker/docker/client/network_connect.go b/vendor/github.com/docker/docker/client/network_connect.go index fa7cc34f..8daf8906 100644 --- a/vendor/github.com/docker/docker/client/network_connect.go +++ b/vendor/github.com/docker/docker/client/network_connect.go @@ -8,16 +8,6 @@ import ( // NetworkConnect connects a container to an existent network in the docker host. func (cli *Client) NetworkConnect(ctx context.Context, networkID, containerID string, config *network.EndpointSettings) error { - networkID, err := trimID("network", networkID) - if err != nil { - return err - } - - containerID, err = trimID("container", containerID) - if err != nil { - return err - } - nc := network.ConnectOptions{ Container: containerID, EndpointConfig: config, diff --git a/vendor/github.com/docker/docker/client/network_disconnect.go b/vendor/github.com/docker/docker/client/network_disconnect.go index d8051df2..aaf428d8 100644 --- a/vendor/github.com/docker/docker/client/network_disconnect.go +++ b/vendor/github.com/docker/docker/client/network_disconnect.go @@ -8,16 +8,6 @@ import ( // NetworkDisconnect disconnects a container from an existent network in the docker host. func (cli *Client) NetworkDisconnect(ctx context.Context, networkID, containerID string, force bool) error { - networkID, err := trimID("network", networkID) - if err != nil { - return err - } - - containerID, err = trimID("container", containerID) - if err != nil { - return err - } - nd := network.DisconnectOptions{ Container: containerID, Force: force, diff --git a/vendor/github.com/docker/docker/client/network_inspect.go b/vendor/github.com/docker/docker/client/network_inspect.go index ad34e80a..afc47de6 100644 --- a/vendor/github.com/docker/docker/client/network_inspect.go +++ b/vendor/github.com/docker/docker/client/network_inspect.go @@ -18,9 +18,8 @@ func (cli *Client) NetworkInspect(ctx context.Context, networkID string, options // NetworkInspectWithRaw returns the information for a specific network configured in the docker host and its raw representation. func (cli *Client) NetworkInspectWithRaw(ctx context.Context, networkID string, options network.InspectOptions) (network.Inspect, []byte, error) { - networkID, err := trimID("network", networkID) - if err != nil { - return network.Inspect{}, nil, err + if networkID == "" { + return network.Inspect{}, nil, objectNotFoundError{object: "network", id: networkID} } query := url.Values{} if options.Verbose { diff --git a/vendor/github.com/docker/docker/client/network_prune.go b/vendor/github.com/docker/docker/client/network_prune.go index 4f089438..708cc61a 100644 --- a/vendor/github.com/docker/docker/client/network_prune.go +++ b/vendor/github.com/docker/docker/client/network_prune.go @@ -11,24 +11,25 @@ import ( // NetworksPrune requests the daemon to delete unused networks func (cli *Client) NetworksPrune(ctx context.Context, pruneFilters filters.Args) (network.PruneReport, error) { + var report network.PruneReport + if err := cli.NewVersionError(ctx, "1.25", "network prune"); err != nil { - return network.PruneReport{}, err + return report, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return network.PruneReport{}, err + return report, err } serverResp, err := cli.post(ctx, "/networks/prune", query, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return network.PruneReport{}, err + return report, err } - var report network.PruneReport if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return network.PruneReport{}, fmt.Errorf("Error retrieving network prune report: %v", err) + return report, fmt.Errorf("Error retrieving network prune report: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/network_remove.go b/vendor/github.com/docker/docker/client/network_remove.go index 89fdaaf3..9d6c6cef 100644 --- a/vendor/github.com/docker/docker/client/network_remove.go +++ b/vendor/github.com/docker/docker/client/network_remove.go @@ -4,10 +4,6 @@ import "context" // NetworkRemove removes an existent network from the docker host. func (cli *Client) NetworkRemove(ctx context.Context, networkID string) error { - networkID, err := trimID("network", networkID) - if err != nil { - return err - } resp, err := cli.delete(ctx, "/networks/"+networkID, nil, nil) defer ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/node_inspect.go b/vendor/github.com/docker/docker/client/node_inspect.go index 458fe616..95ab9b1b 100644 --- a/vendor/github.com/docker/docker/client/node_inspect.go +++ b/vendor/github.com/docker/docker/client/node_inspect.go @@ -11,9 +11,8 @@ import ( // NodeInspectWithRaw returns the node information. func (cli *Client) NodeInspectWithRaw(ctx context.Context, nodeID string) (swarm.Node, []byte, error) { - nodeID, err := trimID("node", nodeID) - if err != nil { - return swarm.Node{}, nil, err + if nodeID == "" { + return swarm.Node{}, nil, objectNotFoundError{object: "node", id: nodeID} } serverResp, err := cli.get(ctx, "/nodes/"+nodeID, nil, nil) defer ensureReaderClosed(serverResp) diff --git a/vendor/github.com/docker/docker/client/node_remove.go b/vendor/github.com/docker/docker/client/node_remove.go index 81f8fed6..e44436de 100644 --- a/vendor/github.com/docker/docker/client/node_remove.go +++ b/vendor/github.com/docker/docker/client/node_remove.go @@ -9,11 +9,6 @@ import ( // NodeRemove removes a Node. func (cli *Client) NodeRemove(ctx context.Context, nodeID string, options types.NodeRemoveOptions) error { - nodeID, err := trimID("node", nodeID) - if err != nil { - return err - } - query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/node_update.go b/vendor/github.com/docker/docker/client/node_update.go index 10e21866..0d0fc3b7 100644 --- a/vendor/github.com/docker/docker/client/node_update.go +++ b/vendor/github.com/docker/docker/client/node_update.go @@ -9,11 +9,6 @@ import ( // NodeUpdate updates a Node. func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, version swarm.Version, node swarm.NodeSpec) error { - nodeID, err := trimID("node", nodeID) - if err != nil { - return err - } - query := url.Values{} query.Set("version", version.String()) resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, node, nil) diff --git a/vendor/github.com/docker/docker/client/options.go b/vendor/github.com/docker/docker/client/options.go index 85b12447..ddb0ca39 100644 --- a/vendor/github.com/docker/docker/client/options.go +++ b/vendor/github.com/docker/docker/client/options.go @@ -6,7 +6,6 @@ import ( "net/http" "os" "path/filepath" - "strings" "time" "github.com/docker/go-connections/sockets" @@ -195,8 +194,8 @@ func WithTLSClientConfigFromEnv() Opt { // (see [WithAPIVersionNegotiation]). func WithVersion(version string) Opt { return func(c *Client) error { - if v := strings.TrimPrefix(version, "v"); v != "" { - c.version = v + if version != "" { + c.version = version c.manualOverride = true } return nil diff --git a/vendor/github.com/docker/docker/client/plugin_disable.go b/vendor/github.com/docker/docker/client/plugin_disable.go index 9fabe77b..01f6574f 100644 --- a/vendor/github.com/docker/docker/client/plugin_disable.go +++ b/vendor/github.com/docker/docker/client/plugin_disable.go @@ -9,10 +9,6 @@ import ( // PluginDisable disables a plugin func (cli *Client) PluginDisable(ctx context.Context, name string, options types.PluginDisableOptions) error { - name, err := trimID("plugin", name) - if err != nil { - return err - } query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/plugin_enable.go b/vendor/github.com/docker/docker/client/plugin_enable.go index 492d0bcf..736da48b 100644 --- a/vendor/github.com/docker/docker/client/plugin_enable.go +++ b/vendor/github.com/docker/docker/client/plugin_enable.go @@ -10,10 +10,6 @@ import ( // PluginEnable enables a plugin func (cli *Client) PluginEnable(ctx context.Context, name string, options types.PluginEnableOptions) error { - name, err := trimID("plugin", name) - if err != nil { - return err - } query := url.Values{} query.Set("timeout", strconv.Itoa(options.Timeout)) diff --git a/vendor/github.com/docker/docker/client/plugin_inspect.go b/vendor/github.com/docker/docker/client/plugin_inspect.go index 6d8bb94d..f09e4606 100644 --- a/vendor/github.com/docker/docker/client/plugin_inspect.go +++ b/vendor/github.com/docker/docker/client/plugin_inspect.go @@ -11,9 +11,8 @@ import ( // PluginInspectWithRaw inspects an existing plugin func (cli *Client) PluginInspectWithRaw(ctx context.Context, name string) (*types.Plugin, []byte, error) { - name, err := trimID("plugin", name) - if err != nil { - return nil, nil, err + if name == "" { + return nil, nil, objectNotFoundError{object: "plugin", id: name} } resp, err := cli.get(ctx, "/plugins/"+name+"/json", nil, nil) defer ensureReaderClosed(resp) diff --git a/vendor/github.com/docker/docker/client/plugin_push.go b/vendor/github.com/docker/docker/client/plugin_push.go index 4624386d..8f68a86e 100644 --- a/vendor/github.com/docker/docker/client/plugin_push.go +++ b/vendor/github.com/docker/docker/client/plugin_push.go @@ -10,10 +10,6 @@ import ( // PluginPush pushes a plugin to a registry func (cli *Client) PluginPush(ctx context.Context, name string, registryAuth string) (io.ReadCloser, error) { - name, err := trimID("plugin", name) - if err != nil { - return nil, err - } resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, http.Header{ registry.AuthHeader: {registryAuth}, }) diff --git a/vendor/github.com/docker/docker/client/plugin_remove.go b/vendor/github.com/docker/docker/client/plugin_remove.go index 6ee107e3..4cd66958 100644 --- a/vendor/github.com/docker/docker/client/plugin_remove.go +++ b/vendor/github.com/docker/docker/client/plugin_remove.go @@ -9,11 +9,6 @@ import ( // PluginRemove removes a plugin func (cli *Client) PluginRemove(ctx context.Context, name string, options types.PluginRemoveOptions) error { - name, err := trimID("plugin", name) - if err != nil { - return err - } - query := url.Values{} if options.Force { query.Set("force", "1") diff --git a/vendor/github.com/docker/docker/client/plugin_set.go b/vendor/github.com/docker/docker/client/plugin_set.go index e2a79838..dcf5752c 100644 --- a/vendor/github.com/docker/docker/client/plugin_set.go +++ b/vendor/github.com/docker/docker/client/plugin_set.go @@ -6,11 +6,6 @@ import ( // PluginSet modifies settings for an existing plugin func (cli *Client) PluginSet(ctx context.Context, name string, args []string) error { - name, err := trimID("plugin", name) - if err != nil { - return err - } - resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, args, nil) ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/plugin_upgrade.go b/vendor/github.com/docker/docker/client/plugin_upgrade.go index 58f0d5f1..5cade450 100644 --- a/vendor/github.com/docker/docker/client/plugin_upgrade.go +++ b/vendor/github.com/docker/docker/client/plugin_upgrade.go @@ -13,12 +13,7 @@ import ( ) // PluginUpgrade upgrades a plugin -func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (io.ReadCloser, error) { - name, err := trimID("plugin", name) - if err != nil { - return nil, err - } - +func (cli *Client) PluginUpgrade(ctx context.Context, name string, options types.PluginInstallOptions) (rc io.ReadCloser, err error) { if err := cli.NewVersionError(ctx, "1.26", "plugin upgrade"); err != nil { return nil, err } diff --git a/vendor/github.com/docker/docker/client/request.go b/vendor/github.com/docker/docker/client/request.go index d7f82230..6eea9b4e 100644 --- a/vendor/github.com/docker/docker/client/request.go +++ b/vendor/github.com/docker/docker/client/request.go @@ -154,24 +154,21 @@ func (cli *Client) doRequest(req *http.Request) (serverResponse, error) { return serverResp, err } - var uErr *url.Error - if errors.As(err, &uErr) { - var nErr *net.OpError - if errors.As(uErr.Err, &nErr) { + if uErr, ok := err.(*url.Error); ok { + if nErr, ok := uErr.Err.(*net.OpError); ok { if os.IsPermission(nErr.Err) { return serverResp, errConnectionFailed{errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)} } } } - var nErr net.Error - if errors.As(err, &nErr) { + if nErr, ok := err.(net.Error); ok { // FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)? if nErr.Timeout() { - return serverResp, connectionFailed(cli.host) + return serverResp, ErrorConnectionFailed(cli.host) } if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") { - return serverResp, connectionFailed(cli.host) + return serverResp, ErrorConnectionFailed(cli.host) } } @@ -237,35 +234,8 @@ func (cli *Client) checkResponseErr(serverResp serverResponse) error { if err := json.Unmarshal(body, &errorResponse); err != nil { return errors.Wrap(err, "Error reading JSON") } - if errorResponse.Message == "" { - // Error-message is empty, which means that we successfully parsed the - // JSON-response (no error produced), but it didn't contain an error - // message. This could either be because the response was empty, or - // the response was valid JSON, but not with the expected schema - // ([types.ErrorResponse]). - // - // We cannot use "strict" JSON handling (json.NewDecoder with DisallowUnknownFields) - // due to the API using an open schema (we must anticipate fields - // being added to [types.ErrorResponse] in the future, and not - // reject those responses. - // - // For these cases, we construct an error with the status-code - // returned, but we could consider returning (a truncated version - // of) the actual response as-is. - // - // TODO(thaJeztah): consider adding a log.Debug to allow clients to debug the actual response when enabling debug logging. - daemonErr = fmt.Errorf(`API returned a %d (%s) but provided no error-message`, - serverResp.statusCode, - http.StatusText(serverResp.statusCode), - ) - } else { - daemonErr = errors.New(strings.TrimSpace(errorResponse.Message)) - } + daemonErr = errors.New(strings.TrimSpace(errorResponse.Message)) } else { - // Fall back to returning the response as-is for API versions < 1.24 - // that didn't support JSON error responses, and for situations - // where a plain text error is returned. This branch may also catch - // situations where a proxy is involved, returning a HTML response. daemonErr = errors.New(strings.TrimSpace(string(body))) } return errors.Wrap(daemonErr, "Error response from daemon") diff --git a/vendor/github.com/docker/docker/client/secret_inspect.go b/vendor/github.com/docker/docker/client/secret_inspect.go index cf160c60..a9cb5988 100644 --- a/vendor/github.com/docker/docker/client/secret_inspect.go +++ b/vendor/github.com/docker/docker/client/secret_inspect.go @@ -11,13 +11,12 @@ import ( // SecretInspectWithRaw returns the secret information with raw data func (cli *Client) SecretInspectWithRaw(ctx context.Context, id string) (swarm.Secret, []byte, error) { - id, err := trimID("secret", id) - if err != nil { - return swarm.Secret{}, nil, err - } if err := cli.NewVersionError(ctx, "1.25", "secret inspect"); err != nil { return swarm.Secret{}, nil, err } + if id == "" { + return swarm.Secret{}, nil, objectNotFoundError{object: "secret", id: id} + } resp, err := cli.get(ctx, "/secrets/"+id, nil, nil) defer ensureReaderClosed(resp) if err != nil { diff --git a/vendor/github.com/docker/docker/client/secret_remove.go b/vendor/github.com/docker/docker/client/secret_remove.go index 7ea2acbf..079ed673 100644 --- a/vendor/github.com/docker/docker/client/secret_remove.go +++ b/vendor/github.com/docker/docker/client/secret_remove.go @@ -4,10 +4,6 @@ import "context" // SecretRemove removes a secret. func (cli *Client) SecretRemove(ctx context.Context, id string) error { - id, err := trimID("secret", id) - if err != nil { - return err - } if err := cli.NewVersionError(ctx, "1.25", "secret remove"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/secret_update.go b/vendor/github.com/docker/docker/client/secret_update.go index 60d21a6f..9dfe6719 100644 --- a/vendor/github.com/docker/docker/client/secret_update.go +++ b/vendor/github.com/docker/docker/client/secret_update.go @@ -9,10 +9,6 @@ import ( // SecretUpdate attempts to update a secret. func (cli *Client) SecretUpdate(ctx context.Context, id string, version swarm.Version, secret swarm.SecretSpec) error { - id, err := trimID("secret", id) - if err != nil { - return err - } if err := cli.NewVersionError(ctx, "1.25", "secret update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/client/service_inspect.go b/vendor/github.com/docker/docker/client/service_inspect.go index 9efcca58..cee020c9 100644 --- a/vendor/github.com/docker/docker/client/service_inspect.go +++ b/vendor/github.com/docker/docker/client/service_inspect.go @@ -14,11 +14,9 @@ import ( // ServiceInspectWithRaw returns the service information and the raw data. func (cli *Client) ServiceInspectWithRaw(ctx context.Context, serviceID string, opts types.ServiceInspectOptions) (swarm.Service, []byte, error) { - serviceID, err := trimID("service", serviceID) - if err != nil { - return swarm.Service{}, nil, err + if serviceID == "" { + return swarm.Service{}, nil, objectNotFoundError{object: "service", id: serviceID} } - query := url.Values{} query.Set("insertDefaults", fmt.Sprintf("%v", opts.InsertDefaults)) serverResp, err := cli.get(ctx, "/services/"+serviceID, query, nil) diff --git a/vendor/github.com/docker/docker/client/service_logs.go b/vendor/github.com/docker/docker/client/service_logs.go index 9281194a..e9e30a2a 100644 --- a/vendor/github.com/docker/docker/client/service_logs.go +++ b/vendor/github.com/docker/docker/client/service_logs.go @@ -14,11 +14,6 @@ import ( // ServiceLogs returns the logs generated by a service in an io.ReadCloser. // It's up to the caller to close the stream. func (cli *Client) ServiceLogs(ctx context.Context, serviceID string, options container.LogsOptions) (io.ReadCloser, error) { - serviceID, err := trimID("service", serviceID) - if err != nil { - return nil, err - } - query := url.Values{} if options.ShowStdout { query.Set("stdout", "1") diff --git a/vendor/github.com/docker/docker/client/service_remove.go b/vendor/github.com/docker/docker/client/service_remove.go index 93c949e4..2c46326e 100644 --- a/vendor/github.com/docker/docker/client/service_remove.go +++ b/vendor/github.com/docker/docker/client/service_remove.go @@ -4,11 +4,6 @@ import "context" // ServiceRemove kills and removes a service. func (cli *Client) ServiceRemove(ctx context.Context, serviceID string) error { - serviceID, err := trimID("service", serviceID) - if err != nil { - return err - } - resp, err := cli.delete(ctx, "/services/"+serviceID, nil, nil) defer ensureReaderClosed(resp) return err diff --git a/vendor/github.com/docker/docker/client/service_update.go b/vendor/github.com/docker/docker/client/service_update.go index aa7da207..d2f03f02 100644 --- a/vendor/github.com/docker/docker/client/service_update.go +++ b/vendor/github.com/docker/docker/client/service_update.go @@ -16,10 +16,7 @@ import ( // It should be the value as set *before* the update. You can find this value in the Meta field // of swarm.Service, which can be found using ServiceInspectWithRaw. func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (swarm.ServiceUpdateResponse, error) { - serviceID, err := trimID("service", serviceID) - if err != nil { - return swarm.ServiceUpdateResponse{}, err - } + response := swarm.ServiceUpdateResponse{} // Make sure we negotiated (if the client is configured to do so), // as code below contains API-version specific handling of options. @@ -27,7 +24,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version // Normally, version-negotiation (if enabled) would not happen until // the API request is made. if err := cli.checkVersion(ctx); err != nil { - return swarm.ServiceUpdateResponse{}, err + return response, err } query := url.Values{} @@ -42,7 +39,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version query.Set("version", version.String()) if err := validateServiceSpec(service); err != nil { - return swarm.ServiceUpdateResponse{}, err + return response, err } // ensure that the image is tagged @@ -77,10 +74,9 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, service, headers) defer ensureReaderClosed(resp) if err != nil { - return swarm.ServiceUpdateResponse{}, err + return response, err } - response := swarm.ServiceUpdateResponse{} err = json.NewDecoder(resp.body).Decode(&response) if resolveWarning != "" { response.Warnings = append(response.Warnings, resolveWarning) diff --git a/vendor/github.com/docker/docker/client/task_inspect.go b/vendor/github.com/docker/docker/client/task_inspect.go index 898ad3e4..dde1f6c5 100644 --- a/vendor/github.com/docker/docker/client/task_inspect.go +++ b/vendor/github.com/docker/docker/client/task_inspect.go @@ -11,11 +11,9 @@ import ( // TaskInspectWithRaw returns the task information and its raw representation. func (cli *Client) TaskInspectWithRaw(ctx context.Context, taskID string) (swarm.Task, []byte, error) { - taskID, err := trimID("task", taskID) - if err != nil { - return swarm.Task{}, nil, err + if taskID == "" { + return swarm.Task{}, nil, objectNotFoundError{object: "task", id: taskID} } - serverResp, err := cli.get(ctx, "/tasks/"+taskID, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { diff --git a/vendor/github.com/docker/docker/client/utils.go b/vendor/github.com/docker/docker/client/utils.go index 925d4d8d..7f3ff44e 100644 --- a/vendor/github.com/docker/docker/client/utils.go +++ b/vendor/github.com/docker/docker/client/utils.go @@ -1,35 +1,13 @@ package client // import "github.com/docker/docker/client" import ( - "encoding/json" - "fmt" "net/url" - "strings" + "regexp" "github.com/docker/docker/api/types/filters" - "github.com/docker/docker/errdefs" - "github.com/docker/docker/internal/lazyregexp" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) -var headerRegexp = lazyregexp.New(`\ADocker/.+\s\((.+)\)\z`) - -type emptyIDError string - -func (e emptyIDError) InvalidParameter() {} - -func (e emptyIDError) Error() string { - return "invalid " + string(e) + " name or ID: value is empty" -} - -// trimID trims the given object-ID / name, returning an error if it's empty. -func trimID(objType, id string) (string, error) { - id = strings.TrimSpace(id) - if len(id) == 0 { - return "", emptyIDError(objType) - } - return id, nil -} +var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`) // getDockerOS returns the operating system based on the server header from the daemon. func getDockerOS(serverHeader string) string { @@ -54,43 +32,3 @@ func getFiltersQuery(f filters.Args) (url.Values, error) { } return query, nil } - -// encodePlatforms marshals the given platform(s) to JSON format, to -// be used for query-parameters for filtering / selecting platforms. -func encodePlatforms(platform ...ocispec.Platform) ([]string, error) { - if len(platform) == 0 { - return []string{}, nil - } - if len(platform) == 1 { - p, err := encodePlatform(&platform[0]) - if err != nil { - return nil, err - } - return []string{p}, nil - } - - seen := make(map[string]struct{}, len(platform)) - out := make([]string, 0, len(platform)) - for i := range platform { - p, err := encodePlatform(&platform[i]) - if err != nil { - return nil, err - } - if _, ok := seen[p]; !ok { - out = append(out, p) - seen[p] = struct{}{} - } - } - return out, nil -} - -// encodePlatform marshals the given platform to JSON format, to -// be used for query-parameters for filtering / selecting platforms. It -// is used as a helper for encodePlatforms, -func encodePlatform(platform *ocispec.Platform) (string, error) { - p, err := json.Marshal(platform) - if err != nil { - return "", errdefs.InvalidParameter(fmt.Errorf("invalid platform: %v", err)) - } - return string(p), nil -} diff --git a/vendor/github.com/docker/docker/client/volume_inspect.go b/vendor/github.com/docker/docker/client/volume_inspect.go index d841d1c5..b3ba4e60 100644 --- a/vendor/github.com/docker/docker/client/volume_inspect.go +++ b/vendor/github.com/docker/docker/client/volume_inspect.go @@ -17,9 +17,8 @@ func (cli *Client) VolumeInspect(ctx context.Context, volumeID string) (volume.V // VolumeInspectWithRaw returns the information about a specific volume in the docker host and its raw representation func (cli *Client) VolumeInspectWithRaw(ctx context.Context, volumeID string) (volume.Volume, []byte, error) { - volumeID, err := trimID("volume", volumeID) - if err != nil { - return volume.Volume{}, nil, err + if volumeID == "" { + return volume.Volume{}, nil, objectNotFoundError{object: "volume", id: volumeID} } var vol volume.Volume diff --git a/vendor/github.com/docker/docker/client/volume_prune.go b/vendor/github.com/docker/docker/client/volume_prune.go index df70389e..9b09c30f 100644 --- a/vendor/github.com/docker/docker/client/volume_prune.go +++ b/vendor/github.com/docker/docker/client/volume_prune.go @@ -11,24 +11,25 @@ import ( // VolumesPrune requests the daemon to delete unused data func (cli *Client) VolumesPrune(ctx context.Context, pruneFilters filters.Args) (volume.PruneReport, error) { + var report volume.PruneReport + if err := cli.NewVersionError(ctx, "1.25", "volume prune"); err != nil { - return volume.PruneReport{}, err + return report, err } query, err := getFiltersQuery(pruneFilters) if err != nil { - return volume.PruneReport{}, err + return report, err } serverResp, err := cli.post(ctx, "/volumes/prune", query, nil, nil) defer ensureReaderClosed(serverResp) if err != nil { - return volume.PruneReport{}, err + return report, err } - var report volume.PruneReport if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil { - return volume.PruneReport{}, fmt.Errorf("Error retrieving volume prune report: %v", err) + return report, fmt.Errorf("Error retrieving volume prune report: %v", err) } return report, nil diff --git a/vendor/github.com/docker/docker/client/volume_remove.go b/vendor/github.com/docker/docker/client/volume_remove.go index eefd9ce4..b8bdc5ae 100644 --- a/vendor/github.com/docker/docker/client/volume_remove.go +++ b/vendor/github.com/docker/docker/client/volume_remove.go @@ -9,11 +9,6 @@ import ( // VolumeRemove removes a volume from the docker host. func (cli *Client) VolumeRemove(ctx context.Context, volumeID string, force bool) error { - volumeID, err := trimID("volume", volumeID) - if err != nil { - return err - } - query := url.Values{} if force { // Make sure we negotiated (if the client is configured to do so), diff --git a/vendor/github.com/docker/docker/client/volume_update.go b/vendor/github.com/docker/docker/client/volume_update.go index c91d5e98..151863f0 100644 --- a/vendor/github.com/docker/docker/client/volume_update.go +++ b/vendor/github.com/docker/docker/client/volume_update.go @@ -11,10 +11,6 @@ import ( // VolumeUpdate updates a volume. This only works for Cluster Volumes, and // only some fields can be updated. func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, version swarm.Version, options volume.UpdateOptions) error { - volumeID, err := trimID("volume", volumeID) - if err != nil { - return err - } if err := cli.NewVersionError(ctx, "1.42", "volume update"); err != nil { return err } diff --git a/vendor/github.com/docker/docker/errdefs/helpers.go b/vendor/github.com/docker/docker/errdefs/helpers.go index ab76e627..042de4b7 100644 --- a/vendor/github.com/docker/docker/errdefs/helpers.go +++ b/vendor/github.com/docker/docker/errdefs/helpers.go @@ -14,9 +14,7 @@ func (e errNotFound) Unwrap() error { return e.error } -// NotFound creates an [ErrNotFound] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrNotFound], +// NotFound is a helper to create an error of the class with the same name from any error type func NotFound(err error) error { if err == nil || IsNotFound(err) { return err @@ -36,9 +34,7 @@ func (e errInvalidParameter) Unwrap() error { return e.error } -// InvalidParameter creates an [ErrInvalidParameter] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrInvalidParameter], +// InvalidParameter is a helper to create an error of the class with the same name from any error type func InvalidParameter(err error) error { if err == nil || IsInvalidParameter(err) { return err @@ -58,9 +54,7 @@ func (e errConflict) Unwrap() error { return e.error } -// Conflict creates an [ErrConflict] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrConflict], +// Conflict is a helper to create an error of the class with the same name from any error type func Conflict(err error) error { if err == nil || IsConflict(err) { return err @@ -80,9 +74,7 @@ func (e errUnauthorized) Unwrap() error { return e.error } -// Unauthorized creates an [ErrUnauthorized] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrUnauthorized], +// Unauthorized is a helper to create an error of the class with the same name from any error type func Unauthorized(err error) error { if err == nil || IsUnauthorized(err) { return err @@ -102,9 +94,7 @@ func (e errUnavailable) Unwrap() error { return e.error } -// Unavailable creates an [ErrUnavailable] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrUnavailable], +// Unavailable is a helper to create an error of the class with the same name from any error type func Unavailable(err error) error { if err == nil || IsUnavailable(err) { return err @@ -124,9 +114,7 @@ func (e errForbidden) Unwrap() error { return e.error } -// Forbidden creates an [ErrForbidden] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrForbidden], +// Forbidden is a helper to create an error of the class with the same name from any error type func Forbidden(err error) error { if err == nil || IsForbidden(err) { return err @@ -146,9 +134,7 @@ func (e errSystem) Unwrap() error { return e.error } -// System creates an [ErrSystem] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrSystem], +// System is a helper to create an error of the class with the same name from any error type func System(err error) error { if err == nil || IsSystem(err) { return err @@ -168,9 +154,7 @@ func (e errNotModified) Unwrap() error { return e.error } -// NotModified creates an [ErrNotModified] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [NotModified], +// NotModified is a helper to create an error of the class with the same name from any error type func NotModified(err error) error { if err == nil || IsNotModified(err) { return err @@ -190,9 +174,7 @@ func (e errNotImplemented) Unwrap() error { return e.error } -// NotImplemented creates an [ErrNotImplemented] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrNotImplemented], +// NotImplemented is a helper to create an error of the class with the same name from any error type func NotImplemented(err error) error { if err == nil || IsNotImplemented(err) { return err @@ -212,9 +194,7 @@ func (e errUnknown) Unwrap() error { return e.error } -// Unknown creates an [ErrUnknown] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrUnknown], +// Unknown is a helper to create an error of the class with the same name from any error type func Unknown(err error) error { if err == nil || IsUnknown(err) { return err @@ -234,9 +214,7 @@ func (e errCancelled) Unwrap() error { return e.error } -// Cancelled creates an [ErrCancelled] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrCancelled], +// Cancelled is a helper to create an error of the class with the same name from any error type func Cancelled(err error) error { if err == nil || IsCancelled(err) { return err @@ -256,9 +234,7 @@ func (e errDeadline) Unwrap() error { return e.error } -// Deadline creates an [ErrDeadline] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrDeadline], +// Deadline is a helper to create an error of the class with the same name from any error type func Deadline(err error) error { if err == nil || IsDeadline(err) { return err @@ -278,9 +254,7 @@ func (e errDataLoss) Unwrap() error { return e.error } -// DataLoss creates an [ErrDataLoss] error from the given error. -// It returns the error as-is if it is either nil (no error) or already implements -// [ErrDataLoss], +// DataLoss is a helper to create an error of the class with the same name from any error type func DataLoss(err error) error { if err == nil || IsDataLoss(err) { return err diff --git a/vendor/github.com/docker/docker/errdefs/http_helpers.go b/vendor/github.com/docker/docker/errdefs/http_helpers.go index 0a8fadd4..ebcd7893 100644 --- a/vendor/github.com/docker/docker/errdefs/http_helpers.go +++ b/vendor/github.com/docker/docker/errdefs/http_helpers.go @@ -11,37 +11,36 @@ func FromStatusCode(err error, statusCode int) error { } switch statusCode { case http.StatusNotFound: - return NotFound(err) + err = NotFound(err) case http.StatusBadRequest: - return InvalidParameter(err) + err = InvalidParameter(err) case http.StatusConflict: - return Conflict(err) + err = Conflict(err) case http.StatusUnauthorized: - return Unauthorized(err) + err = Unauthorized(err) case http.StatusServiceUnavailable: - return Unavailable(err) + err = Unavailable(err) case http.StatusForbidden: - return Forbidden(err) + err = Forbidden(err) case http.StatusNotModified: - return NotModified(err) + err = NotModified(err) case http.StatusNotImplemented: - return NotImplemented(err) + err = NotImplemented(err) case http.StatusInternalServerError: - if IsCancelled(err) || IsSystem(err) || IsUnknown(err) || IsDataLoss(err) || IsDeadline(err) { - return err + if !IsSystem(err) && !IsUnknown(err) && !IsDataLoss(err) && !IsDeadline(err) && !IsCancelled(err) { + err = System(err) } - return System(err) default: switch { case statusCode >= 200 && statusCode < 400: // it's a client error - return err case statusCode >= 400 && statusCode < 500: - return InvalidParameter(err) + err = InvalidParameter(err) case statusCode >= 500 && statusCode < 600: - return System(err) + err = System(err) default: - return Unknown(err) + err = Unknown(err) } } + return err } diff --git a/vendor/github.com/docker/docker/errdefs/is.go b/vendor/github.com/docker/docker/errdefs/is.go index 30ea7e6f..f94034cb 100644 --- a/vendor/github.com/docker/docker/errdefs/is.go +++ b/vendor/github.com/docker/docker/errdefs/is.go @@ -39,79 +39,79 @@ func getImplementer(err error) error { } } -// IsNotFound returns if the passed in error is an [ErrNotFound], +// IsNotFound returns if the passed in error is an ErrNotFound func IsNotFound(err error) bool { _, ok := getImplementer(err).(ErrNotFound) return ok } -// IsInvalidParameter returns if the passed in error is an [ErrInvalidParameter]. +// IsInvalidParameter returns if the passed in error is an ErrInvalidParameter func IsInvalidParameter(err error) bool { _, ok := getImplementer(err).(ErrInvalidParameter) return ok } -// IsConflict returns if the passed in error is an [ErrConflict]. +// IsConflict returns if the passed in error is an ErrConflict func IsConflict(err error) bool { _, ok := getImplementer(err).(ErrConflict) return ok } -// IsUnauthorized returns if the passed in error is an [ErrUnauthorized]. +// IsUnauthorized returns if the passed in error is an ErrUnauthorized func IsUnauthorized(err error) bool { _, ok := getImplementer(err).(ErrUnauthorized) return ok } -// IsUnavailable returns if the passed in error is an [ErrUnavailable]. +// IsUnavailable returns if the passed in error is an ErrUnavailable func IsUnavailable(err error) bool { _, ok := getImplementer(err).(ErrUnavailable) return ok } -// IsForbidden returns if the passed in error is an [ErrForbidden]. +// IsForbidden returns if the passed in error is an ErrForbidden func IsForbidden(err error) bool { _, ok := getImplementer(err).(ErrForbidden) return ok } -// IsSystem returns if the passed in error is an [ErrSystem]. +// IsSystem returns if the passed in error is an ErrSystem func IsSystem(err error) bool { _, ok := getImplementer(err).(ErrSystem) return ok } -// IsNotModified returns if the passed in error is an [ErrNotModified]. +// IsNotModified returns if the passed in error is a NotModified error func IsNotModified(err error) bool { _, ok := getImplementer(err).(ErrNotModified) return ok } -// IsNotImplemented returns if the passed in error is an [ErrNotImplemented]. +// IsNotImplemented returns if the passed in error is an ErrNotImplemented func IsNotImplemented(err error) bool { _, ok := getImplementer(err).(ErrNotImplemented) return ok } -// IsUnknown returns if the passed in error is an [ErrUnknown]. +// IsUnknown returns if the passed in error is an ErrUnknown func IsUnknown(err error) bool { _, ok := getImplementer(err).(ErrUnknown) return ok } -// IsCancelled returns if the passed in error is an [ErrCancelled]. +// IsCancelled returns if the passed in error is an ErrCancelled func IsCancelled(err error) bool { _, ok := getImplementer(err).(ErrCancelled) return ok } -// IsDeadline returns if the passed in error is an [ErrDeadline]. +// IsDeadline returns if the passed in error is an ErrDeadline func IsDeadline(err error) bool { _, ok := getImplementer(err).(ErrDeadline) return ok } -// IsDataLoss returns if the passed in error is an [ErrDataLoss]. +// IsDataLoss returns if the passed in error is an ErrDataLoss func IsDataLoss(err error) bool { _, ok := getImplementer(err).(ErrDataLoss) return ok diff --git a/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go b/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go deleted file mode 100644 index 6334edb6..00000000 --- a/vendor/github.com/docker/docker/internal/lazyregexp/lazyregexp.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Code below was largely copied from golang.org/x/mod@v0.22; -// https://github.com/golang/mod/blob/v0.22.0/internal/lazyregexp/lazyre.go -// with some additional methods added. - -// Package lazyregexp is a thin wrapper over regexp, allowing the use of global -// regexp variables without forcing them to be compiled at init. -package lazyregexp - -import ( - "os" - "regexp" - "strings" - "sync" -) - -// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be -// compiled the first time it is needed. -type Regexp struct { - str string - once sync.Once - rx *regexp.Regexp -} - -func (r *Regexp) re() *regexp.Regexp { - r.once.Do(r.build) - return r.rx -} - -func (r *Regexp) build() { - r.rx = regexp.MustCompile(r.str) - r.str = "" -} - -func (r *Regexp) FindSubmatch(s []byte) [][]byte { - return r.re().FindSubmatch(s) -} - -func (r *Regexp) FindAllStringSubmatch(s string, n int) [][]string { - return r.re().FindAllStringSubmatch(s, n) -} - -func (r *Regexp) FindStringSubmatch(s string) []string { - return r.re().FindStringSubmatch(s) -} - -func (r *Regexp) FindStringSubmatchIndex(s string) []int { - return r.re().FindStringSubmatchIndex(s) -} - -func (r *Regexp) ReplaceAllString(src, repl string) string { - return r.re().ReplaceAllString(src, repl) -} - -func (r *Regexp) FindString(s string) string { - return r.re().FindString(s) -} - -func (r *Regexp) FindAllString(s string, n int) []string { - return r.re().FindAllString(s, n) -} - -func (r *Regexp) MatchString(s string) bool { - return r.re().MatchString(s) -} - -func (r *Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string { - return r.re().ReplaceAllStringFunc(src, repl) -} - -func (r *Regexp) SubexpNames() []string { - return r.re().SubexpNames() -} - -var inTest = len(os.Args) > 0 && strings.HasSuffix(strings.TrimSuffix(os.Args[0], ".exe"), ".test") - -// New creates a new lazy regexp, delaying the compiling work until it is first -// needed. If the code is being run as part of tests, the regexp compiling will -// happen immediately. -func New(str string) *Regexp { - lr := &Regexp{str: str} - if inTest { - // In tests, always compile the regexps early. - lr.re() - } - return lr -} diff --git a/vendor/github.com/docker/docker/pkg/archive/archive.go b/vendor/github.com/docker/docker/pkg/archive/archive.go index b0578040..cde64f08 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive.go @@ -1,5 +1,5 @@ // Package archive provides helper functions for dealing with archive files. -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" @@ -9,26 +9,26 @@ import ( "compress/gzip" "context" "encoding/binary" - "errors" "fmt" "io" "os" "os/exec" "path/filepath" "runtime" - "runtime/debug" "strconv" "strings" - "sync" - "sync/atomic" "syscall" "time" "github.com/containerd/log" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/ioutils" + "github.com/docker/docker/pkg/pools" + "github.com/docker/docker/pkg/system" "github.com/klauspost/compress/zstd" "github.com/moby/patternmatcher" "github.com/moby/sys/sequential" + "github.com/pkg/errors" ) // ImpliedDirectoryMode represents the mode (Unix permissions) applied to directories that are implied by files in a @@ -215,66 +215,17 @@ func gzDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) { return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf) } -type readCloserWrapper struct { - io.Reader - closer func() error - closed atomic.Bool -} - -func (r *readCloserWrapper) Close() error { - if !r.closed.CompareAndSwap(false, true) { - log.G(context.TODO()).Error("subsequent attempt to close readCloserWrapper") - if log.GetLevel() >= log.DebugLevel { - log.G(context.TODO()).Errorf("stack trace: %s", string(debug.Stack())) - } - - return nil - } - if r.closer != nil { - return r.closer() - } - return nil -} - -var ( - bufioReader32KPool = &sync.Pool{ - New: func() interface{} { return bufio.NewReaderSize(nil, 32*1024) }, - } -) - -type bufferedReader struct { - buf *bufio.Reader -} - -func newBufferedReader(r io.Reader) *bufferedReader { - buf := bufioReader32KPool.Get().(*bufio.Reader) - buf.Reset(r) - return &bufferedReader{buf} -} - -func (r *bufferedReader) Read(p []byte) (n int, err error) { - if r.buf == nil { - return 0, io.EOF - } - n, err = r.buf.Read(p) - if err == io.EOF { - r.buf.Reset(nil) - bufioReader32KPool.Put(r.buf) - r.buf = nil - } - return -} - -func (r *bufferedReader) Peek(n int) ([]byte, error) { - if r.buf == nil { - return nil, io.EOF - } - return r.buf.Peek(n) +func wrapReadCloser(readBuf io.ReadCloser, cancel context.CancelFunc) io.ReadCloser { + return ioutils.NewReadCloserWrapper(readBuf, func() error { + cancel() + return readBuf.Close() + }) } // DecompressStream decompresses the archive and returns a ReaderCloser with the decompressed archive. func DecompressStream(archive io.Reader) (io.ReadCloser, error) { - buf := newBufferedReader(archive) + p := pools.BufioReader32KPool + buf := p.Get(archive) bs, err := buf.Peek(10) if err != nil && err != io.EOF { // Note: we'll ignore any io.EOF error because there are some odd @@ -289,9 +240,8 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { compression := DetectCompression(bs) switch compression { case Uncompressed: - return &readCloserWrapper{ - Reader: buf, - }, nil + readBufWrapper := p.NewReadCloserWrapper(buf, buf) + return readBufWrapper, nil case Gzip: ctx, cancel := context.WithCancel(context.Background()) @@ -300,18 +250,12 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { cancel() return nil, err } - return &readCloserWrapper{ - Reader: gzReader, - closer: func() error { - cancel() - return gzReader.Close() - }, - }, nil + readBufWrapper := p.NewReadCloserWrapper(buf, gzReader) + return wrapReadCloser(readBufWrapper, cancel), nil case Bzip2: bz2Reader := bzip2.NewReader(buf) - return &readCloserWrapper{ - Reader: bz2Reader, - }, nil + readBufWrapper := p.NewReadCloserWrapper(buf, bz2Reader) + return readBufWrapper, nil case Xz: ctx, cancel := context.WithCancel(context.Background()) @@ -320,44 +264,32 @@ func DecompressStream(archive io.Reader) (io.ReadCloser, error) { cancel() return nil, err } - - return &readCloserWrapper{ - Reader: xzReader, - closer: func() error { - cancel() - return xzReader.Close() - }, - }, nil + readBufWrapper := p.NewReadCloserWrapper(buf, xzReader) + return wrapReadCloser(readBufWrapper, cancel), nil case Zstd: zstdReader, err := zstd.NewReader(buf) if err != nil { return nil, err } - return &readCloserWrapper{ - Reader: zstdReader, - closer: func() error { - zstdReader.Close() - return nil - }, - }, nil + readBufWrapper := p.NewReadCloserWrapper(buf, zstdReader) + return readBufWrapper, nil default: return nil, fmt.Errorf("Unsupported compression format %s", (&compression).Extension()) } } -type nopWriteCloser struct { - io.Writer -} - -func (nopWriteCloser) Close() error { return nil } - // CompressStream compresses the dest with specified compression algorithm. func CompressStream(dest io.Writer, compression Compression) (io.WriteCloser, error) { + p := pools.BufioWriter32KPool + buf := p.Get(dest) switch compression { case Uncompressed: - return nopWriteCloser{dest}, nil + writeBufWrapper := p.NewWriteCloserWrapper(buf, buf) + return writeBufWrapper, nil case Gzip: - return gzip.NewWriter(dest), nil + gzWriter := gzip.NewWriter(dest) + writeBufWrapper := p.NewWriteCloserWrapper(buf, gzWriter) + return writeBufWrapper, nil case Bzip2, Xz: // archive/bzip2 does not support writing, and there is no xz support at all // However, this is not a problem as docker only currently generates gzipped tars @@ -428,7 +360,7 @@ func ReplaceFileTarWrapper(inputTarStream io.ReadCloser, mods map[string]TarModi pipeWriter.CloseWithError(err) return } - if _, err := copyWithBuffer(tarWriter, tarReader); err != nil { + if _, err := pools.Copy(tarWriter, tarReader); err != nil { pipeWriter.CloseWithError(err) return } @@ -472,35 +404,13 @@ func (compression *Compression) Extension() string { return "" } -// assert that we implement [tar.FileInfoNames]. -// -// TODO(thaJeztah): disabled to allow compiling on < go1.23. un-comment once we drop support for older versions of go. -// var _ tar.FileInfoNames = (*nosysFileInfo)(nil) - // nosysFileInfo hides the system-dependent info of the wrapped FileInfo to // prevent tar.FileInfoHeader from introspecting it and potentially calling into // glibc. -// -// It implements [tar.FileInfoNames] to further prevent [tar.FileInfoHeader] -// from performing any lookups on go1.23 and up. see https://go.dev/issue/50102 type nosysFileInfo struct { os.FileInfo } -// Uname stubs out looking up username. It implements [tar.FileInfoNames] -// to prevent [tar.FileInfoHeader] from loading libraries to perform -// username lookups. -func (fi nosysFileInfo) Uname() (string, error) { - return "", nil -} - -// Gname stubs out looking up group-name. It implements [tar.FileInfoNames] -// to prevent [tar.FileInfoHeader] from loading libraries to perform -// username lookups. -func (fi nosysFileInfo) Gname() (string, error) { - return "", nil -} - func (fi nosysFileInfo) Sys() interface{} { // A Sys value of type *tar.Header is safe as it is system-independent. // The tar.FileInfoHeader function copies the fields into the returned @@ -574,7 +484,7 @@ func ReadSecurityXattrToTarHeader(path string, hdr *tar.Header) error { vfsCapRevision2 = 2 vfsCapRevision3 = 3 ) - capability, _ := lgetxattr(path, "security.capability") + capability, _ := system.Lgetxattr(path, "security.capability") if capability != nil { if capability[versionOffset] == vfsCapRevision3 { // Convert VFS_CAP_REVISION_3 to VFS_CAP_REVISION_2 as root UID makes no @@ -597,6 +507,7 @@ type tarWhiteoutConverter interface { type tarAppender struct { TarWriter *tar.Writer + Buffer *bufio.Writer // for hardlink mapping SeenFiles map[uint64]string @@ -614,11 +525,21 @@ func newTarAppender(idMapping idtools.IdentityMapping, writer io.Writer, chownOp return &tarAppender{ SeenFiles: make(map[uint64]string), TarWriter: tar.NewWriter(writer), + Buffer: pools.BufioWriter32KPool.Get(nil), IdentityMapping: idMapping, ChownOpts: chownOpts, } } +// CanonicalTarNameForPath canonicalizes relativePath to a POSIX-style path using +// forward slashes. It is an alias for [filepath.ToSlash], which is a no-op on +// Linux and Unix. +// +// Deprecated: use [filepath.ToSlash]. This function will be removed in the next release. +func CanonicalTarNameForPath(relativePath string) string { + return filepath.ToSlash(relativePath) +} + // canonicalTarName provides a platform-independent and consistent POSIX-style // path for files and directories to be archived regardless of the platform. func canonicalTarName(name string, isDir bool) string { @@ -731,11 +652,17 @@ func (ta *tarAppender) addTarFile(path, name string) error { return err } - _, err = copyWithBuffer(ta.TarWriter, file) + ta.Buffer.Reset(ta.TarWriter) + defer ta.Buffer.Reset(nil) + _, err = io.Copy(ta.Buffer, file) file.Close() if err != nil { return err } + err = ta.Buffer.Flush() + if err != nil { + return err + } } return nil @@ -778,7 +705,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o if err != nil { return err } - if _, err := copyWithBuffer(file, reader); err != nil { + if _, err := io.Copy(file, reader); err != nil { file.Close() return err } @@ -844,11 +771,11 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o chownOpts = &idtools.Identity{UID: hdr.Uid, GID: hdr.Gid} } if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil { - var msg string + msg := "failed to Lchown %q for UID %d, GID %d" if inUserns && errors.Is(err, syscall.EINVAL) { - msg = " (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)" + msg += " (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)" } - return fmt.Errorf("failed to Lchown %q for UID %d, GID %d%s: %w", path, hdr.Uid, hdr.Gid, msg, err) + return errors.Wrapf(err, msg, path, hdr.Uid, hdr.Gid) } } @@ -858,7 +785,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o if !ok { continue } - if err := lsetxattr(path, xattr, []byte(value), 0); err != nil { + if err := system.Lsetxattr(path, xattr, []byte(value), 0); err != nil { if bestEffortXattrs && errors.Is(err, syscall.ENOTSUP) || errors.Is(err, syscall.EPERM) { // EPERM occurs if modifying xattrs is not allowed. This can // happen when running in userns with restrictions (ChromeOS). @@ -881,22 +808,26 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o return err } - aTime := boundTime(latestTime(hdr.AccessTime, hdr.ModTime)) - mTime := boundTime(hdr.ModTime) + aTime := hdr.AccessTime + if aTime.Before(hdr.ModTime) { + // Last access time should never be before last modified time. + aTime = hdr.ModTime + } - // chtimes doesn't support a NOFOLLOW flag atm + // system.Chtimes doesn't support a NOFOLLOW flag atm if hdr.Typeflag == tar.TypeLink { if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { - if err := chtimes(path, aTime, mTime); err != nil { + if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { return err } } } else if hdr.Typeflag != tar.TypeSymlink { - if err := chtimes(path, aTime, mTime); err != nil { + if err := system.Chtimes(path, aTime, hdr.ModTime); err != nil { return err } } else { - if err := lchtimes(path, aTime, mTime); err != nil { + ts := []syscall.Timespec{timeToTimespec(aTime), timeToTimespec(hdr.ModTime)} + if err := system.LUtimesNano(path, ts); err != nil && err != system.ErrNotSupportedPlatform { return err } } @@ -989,6 +920,9 @@ func (t *Tarballer) Do() { } }() + // this buffer is needed for the duration of this piped stream + defer pools.BufioWriter32KPool.Put(ta.Buffer) + // In general we log errors here but ignore them because // during e.g. a diff operation the container can continue // mutating the filesystem and we can see transient errors @@ -1144,6 +1078,8 @@ func (t *Tarballer) Do() { // Unpack unpacks the decompressedArchive to dest with options. func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) error { tr := tar.NewReader(decompressedArchive) + trBuf := pools.BufioReader32KPool.Get(nil) + defer pools.BufioReader32KPool.Put(trBuf) var dirs []*tar.Header whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat) @@ -1220,6 +1156,7 @@ loop: } } } + trBuf.Reset(tr) if err := remapIDs(options.IDMap, hdr); err != nil { return err @@ -1235,7 +1172,7 @@ loop: } } - if err := createTarFile(path, dest, hdr, tr, options); err != nil { + if err := createTarFile(path, dest, hdr, trBuf, options); err != nil { return err } @@ -1250,7 +1187,7 @@ loop: // #nosec G305 -- The header was checked for path traversal before it was appended to the dirs slice. path := filepath.Join(dest, hdr.Name) - if err := chtimes(path, boundTime(latestTime(hdr.AccessTime, hdr.ModTime)), boundTime(hdr.ModTime)); err != nil { + if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { return err } } @@ -1399,7 +1336,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { dst = filepath.Join(dst, filepath.Base(src)) } // Create the holding directory if necessary - if err := os.MkdirAll(filepath.Dir(dst), 0o700); err != nil { + if err := system.MkdirAll(filepath.Dir(dst), 0o700); err != nil { return err } @@ -1438,7 +1375,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) { if err := tw.WriteHeader(hdr); err != nil { return err } - if _, err := copyWithBuffer(tw, srcF); err != nil { + if _, err := io.Copy(tw, srcF); err != nil { return err } return nil @@ -1496,14 +1433,68 @@ func cmdStream(cmd *exec.Cmd, input io.Reader) (io.ReadCloser, error) { close(done) }() - return &readCloserWrapper{ - Reader: pipeR, - closer: func() error { - // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as - // cmd.Wait waits for any non-file stdout/stderr/stdin to close. - err := pipeR.Close() - <-done - return err - }, - }, nil + return ioutils.NewReadCloserWrapper(pipeR, func() error { + // Close pipeR, and then wait for the command to complete before returning. We have to close pipeR first, as + // cmd.Wait waits for any non-file stdout/stderr/stdin to close. + err := pipeR.Close() + <-done + return err + }), nil +} + +// NewTempArchive reads the content of src into a temporary file, and returns the contents +// of that file as an archive. The archive can only be read once - as soon as reading completes, +// the file will be deleted. +// +// Deprecated: NewTempArchive is only used in tests and will be removed in the next release. +func NewTempArchive(src io.Reader, dir string) (*TempArchive, error) { + f, err := os.CreateTemp(dir, "") + if err != nil { + return nil, err + } + if _, err := io.Copy(f, src); err != nil { + return nil, err + } + if _, err := f.Seek(0, 0); err != nil { + return nil, err + } + st, err := f.Stat() + if err != nil { + return nil, err + } + size := st.Size() + return &TempArchive{File: f, Size: size}, nil +} + +// TempArchive is a temporary archive. The archive can only be read once - as soon as reading completes, +// the file will be deleted. +// +// Deprecated: TempArchive is only used in tests and will be removed in the next release. +type TempArchive struct { + *os.File + Size int64 // Pre-computed from Stat().Size() as a convenience + read int64 + closed bool +} + +// Close closes the underlying file if it's still open, or does a no-op +// to allow callers to try to close the TempArchive multiple times safely. +func (archive *TempArchive) Close() error { + if archive.closed { + return nil + } + + archive.closed = true + + return archive.File.Close() +} + +func (archive *TempArchive) Read(data []byte) (int, error) { + n, err := archive.File.Read(data) + archive.read += int64(n) + if err != nil || archive.read == archive.Size { + archive.Close() + os.Remove(archive.File.Name()) + } + return n, err } diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go b/vendor/github.com/docker/docker/pkg/archive/archive_linux.go index 631d2e3c..b9d2a538 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_linux.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_linux.go @@ -1,13 +1,14 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" - "fmt" "os" "path/filepath" "strings" + "github.com/docker/docker/pkg/system" "github.com/moby/sys/userns" + "github.com/pkg/errors" "golang.org/x/sys/unix" ) @@ -38,7 +39,7 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os } // convert opaque dirs to AUFS format by writing an empty file with the prefix - opaque, err := lgetxattr(path, opaqueXattrName) + opaque, err := system.Lgetxattr(path, opaqueXattrName) if err != nil { return nil, err } @@ -78,7 +79,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo err := unix.Setxattr(dir, opaqueXattrName, []byte{'y'}, 0) if err != nil { - return false, fmt.Errorf("setxattr('%s', %s=y): %w", dir, opaqueXattrName, err) + return false, errors.Wrapf(err, "setxattr(%q, %s=y)", dir, opaqueXattrName) } // don't write the file itself return false, err @@ -90,7 +91,7 @@ func (c overlayWhiteoutConverter) ConvertRead(hdr *tar.Header, path string) (boo originalPath := filepath.Join(dir, originalBase) if err := unix.Mknod(originalPath, unix.S_IFCHR, 0); err != nil { - return false, fmt.Errorf("failed to mknod('%s', S_IFCHR, 0): %w", originalPath, err) + return false, errors.Wrapf(err, "failed to mknod(%q, S_IFCHR, 0)", originalPath) } if err := os.Chown(originalPath, hdr.Uid, hdr.Gid); err != nil { return false, err diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_other.go b/vendor/github.com/docker/docker/pkg/archive/archive_other.go index 6495549f..7dee1f7a 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_other.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_other.go @@ -1,6 +1,6 @@ //go:build !linux -package archive +package archive // import "github.com/docker/docker/pkg/archive" func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter { return nil diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go b/vendor/github.com/docker/docker/pkg/archive/archive_unix.go index 9c70d178..f559a305 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_unix.go @@ -1,6 +1,6 @@ //go:build !windows -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" @@ -12,6 +12,7 @@ import ( "syscall" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/system" "golang.org/x/sys/unix" ) @@ -108,7 +109,7 @@ func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { mode |= unix.S_IFIFO } - return mknod(path, mode, unix.Mkdev(uint32(hdr.Devmajor), uint32(hdr.Devminor))) + return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))) } func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { diff --git a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go index 03160816..e25c64b4 100644 --- a/vendor/github.com/docker/docker/pkg/archive/archive_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/archive_windows.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" diff --git a/vendor/github.com/docker/docker/pkg/archive/changes.go b/vendor/github.com/docker/docker/pkg/archive/changes.go index 79c810a6..5f12ca40 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" @@ -6,15 +6,17 @@ import ( "context" "fmt" "io" - "io/fs" "os" "path/filepath" "sort" "strings" + "syscall" "time" "github.com/containerd/log" "github.com/docker/docker/pkg/idtools" + "github.com/docker/docker/pkg/pools" + "github.com/docker/docker/pkg/system" ) // ChangeType represents the change type. @@ -72,6 +74,11 @@ func sameFsTime(a, b time.Time) bool { (a.Nanosecond() == 0 || b.Nanosecond() == 0)) } +func sameFsTimeSpec(a, b syscall.Timespec) bool { + return a.Sec == b.Sec && + (a.Nsec == b.Nsec || a.Nsec == 0 || b.Nsec == 0) +} + // Changes walks the path rw and determines changes for the files in the path, // with respect to the parent layers func Changes(layers []string, rw string) ([]Change, error) { @@ -203,7 +210,7 @@ func changes(layers []string, rw string, dc deleteChange, sc skipChange) ([]Chan type FileInfo struct { parent *FileInfo name string - stat fs.FileInfo + stat *system.StatT children map[string]*FileInfo capability []byte added bool @@ -388,6 +395,9 @@ func ExportChanges(dir string, changes []Change, idMap idtools.IdentityMapping) go func() { ta := newTarAppender(idMap, writer, nil) + // this buffer is needed for the duration of this piped stream + defer pools.BufioWriter32KPool.Put(ta.Buffer) + sort.Sort(changesByPath(changes)) // In general we log errors here but ignore them because diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go index 6bb35848..81fcbc5b 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_linux.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_linux.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "bytes" @@ -9,6 +9,7 @@ import ( "syscall" "unsafe" + "github.com/docker/docker/pkg/system" "golang.org/x/sys/unix" ) @@ -73,8 +74,12 @@ func walkchunk(path string, fi os.FileInfo, dir string, root *FileInfo) error { parent: parent, } cpath := filepath.Join(dir, path) - info.stat = fi - info.capability, _ = lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access + stat, err := system.FromStatT(fi.Sys().(*syscall.Stat_t)) + if err != nil { + return err + } + info.stat = stat + info.capability, _ = system.Lgetxattr(cpath, "security.capability") // lgetxattr(2): fs access parent.children[info.name] = info return nil } @@ -256,13 +261,13 @@ func readdirnames(dirname string) (names []nameIno, err error) { func parseDirent(buf []byte, names []nameIno) (consumed int, newnames []nameIno) { origlen := len(buf) for len(buf) > 0 { - dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited" + dirent := (*unix.Dirent)(unsafe.Pointer(&buf[0])) buf = buf[dirent.Reclen:] if dirent.Ino == 0 { // File absent in directory. continue } - b := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) // #nosec G103 -- Ignore "G103: Use of unsafe calls should be audited" - name := string(b[0:clen(b[:])]) + bytes := (*[10000]byte)(unsafe.Pointer(&dirent.Name[0])) + name := string(bytes[0:clen(bytes[:])]) if name == "." || name == ".." { // Useless names continue } diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_other.go b/vendor/github.com/docker/docker/pkg/archive/changes_other.go index a8a3a5a6..28f741a2 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_other.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_other.go @@ -1,6 +1,6 @@ //go:build !linux -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "fmt" @@ -8,6 +8,8 @@ import ( "path/filepath" "runtime" "strings" + + "github.com/docker/docker/pkg/system" ) func collectFileInfoForChanges(oldDir, newDir string) (*FileInfo, *FileInfo, error) { @@ -70,7 +72,7 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) { return fmt.Errorf("collectFileInfo: Unexpectedly no parent for %s", relPath) } - s, err := os.Lstat(path) + s, err := system.Lstat(path) if err != nil { return err } @@ -82,7 +84,11 @@ func collectFileInfo(sourceDir string) (*FileInfo, error) { stat: s, } - info.capability, _ = lgetxattr(path, "security.capability") + // system.Lgetxattr is only implemented on Linux and produces an error + // on other platforms. This code is intentionally left commented-out + // as a reminder to include this code if this would ever be implemented + // on other platforms. + // info.capability, _ = system.Lgetxattr(path, "security.capability") parent.children[info.name] = info diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go index 4dd98bd2..853c73ee 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_unix.go @@ -1,21 +1,21 @@ //go:build !windows -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( - "io/fs" "os" "syscall" + + "github.com/docker/docker/pkg/system" + "golang.org/x/sys/unix" ) -func statDifferent(oldStat fs.FileInfo, newStat fs.FileInfo) bool { - oldSys := oldStat.Sys().(*syscall.Stat_t) - newSys := newStat.Sys().(*syscall.Stat_t) +func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { // Don't look at size for dirs, its not a good measure of change if oldStat.Mode() != newStat.Mode() || - oldSys.Uid != newSys.Uid || - oldSys.Gid != newSys.Gid || - oldSys.Rdev != newSys.Rdev || + oldStat.UID() != newStat.UID() || + oldStat.GID() != newStat.GID() || + oldStat.Rdev() != newStat.Rdev() || // Don't look at size or modification time for dirs, its not a good // measure of change. See https://github.com/moby/moby/issues/9874 // for a description of the issue with modification time, and @@ -23,15 +23,15 @@ func statDifferent(oldStat fs.FileInfo, newStat fs.FileInfo) bool { // (Note that in the Windows implementation of this function, // modification time IS taken as a change). See // https://github.com/moby/moby/pull/37982 for more information. - (!oldStat.Mode().IsDir() && - (!sameFsTime(oldStat.ModTime(), newStat.ModTime()) || (oldStat.Size() != newStat.Size()))) { + (oldStat.Mode()&unix.S_IFDIR != unix.S_IFDIR && + (!sameFsTimeSpec(oldStat.Mtim(), newStat.Mtim()) || (oldStat.Size() != newStat.Size()))) { return true } return false } func (info *FileInfo) isDir() bool { - return info.parent == nil || info.stat.Mode().IsDir() + return info.parent == nil || info.stat.Mode()&unix.S_IFDIR != 0 } func getIno(fi os.FileInfo) uint64 { diff --git a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go index c89605c7..9906685e 100644 --- a/vendor/github.com/docker/docker/pkg/archive/changes_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/changes_windows.go @@ -1,18 +1,19 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( - "io/fs" "os" + + "github.com/docker/docker/pkg/system" ) -func statDifferent(oldStat fs.FileInfo, newStat fs.FileInfo) bool { +func statDifferent(oldStat *system.StatT, newStat *system.StatT) bool { // Note there is slight difference between the Linux and Windows // implementations here. Due to https://github.com/moby/moby/issues/9874, // and the fix at https://github.com/moby/moby/pull/11422, Linux does not // consider a change to the directory time as a change. Windows on NTFS // does. See https://github.com/moby/moby/pull/37982 for more information. - if !sameFsTime(oldStat.ModTime(), newStat.ModTime()) || + if !sameFsTime(oldStat.Mtim(), newStat.Mtim()) || oldStat.Mode() != newStat.Mode() || oldStat.Size() != newStat.Size() && !oldStat.Mode().IsDir() { return true diff --git a/vendor/github.com/docker/docker/pkg/archive/copy.go b/vendor/github.com/docker/docker/pkg/archive/copy.go index cddf18ec..01eadc30 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" @@ -8,9 +8,9 @@ import ( "os" "path/filepath" "strings" - "sync" "github.com/containerd/log" + "github.com/docker/docker/pkg/system" ) // Errors used or returned by this file. @@ -21,17 +21,6 @@ var ( ErrInvalidCopySource = errors.New("invalid copy source content") ) -var copyPool = sync.Pool{ - New: func() interface{} { s := make([]byte, 32*1024); return &s }, -} - -func copyWithBuffer(dst io.Writer, src io.Reader) (written int64, err error) { - buf := copyPool.Get().(*[]byte) - written, err = io.CopyBuffer(dst, src, *buf) - copyPool.Put(buf) - return -} - // PreserveTrailingDotOrSeparator returns the given cleaned path (after // processing using any utility functions from the path or filepath stdlib // packages) and appends a trailing `/.` or `/` if its corresponding original @@ -214,7 +203,7 @@ func CopyInfoDestinationPath(path string) (info CopyInfo, err error) { return CopyInfo{}, err } - if !filepath.IsAbs(linkTarget) { + if !system.IsAbs(linkTarget) { // Join with the parent directory. dstParent, _ := SplitPathDirEntry(path) linkTarget = filepath.Join(dstParent, linkTarget) diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go index f5792824..065bd4ad 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy_unix.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy_unix.go @@ -1,6 +1,6 @@ //go:build !windows -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "path/filepath" diff --git a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go index 2b775b45..a878d1ba 100644 --- a/vendor/github.com/docker/docker/pkg/archive/copy_windows.go +++ b/vendor/github.com/docker/docker/pkg/archive/copy_windows.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "path/filepath" diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go b/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go deleted file mode 100644 index aa8e2915..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/dev_freebsd.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build freebsd - -package archive - -import "golang.org/x/sys/unix" - -var mknod = unix.Mknod diff --git a/vendor/github.com/docker/docker/pkg/archive/dev_unix.go b/vendor/github.com/docker/docker/pkg/archive/dev_unix.go deleted file mode 100644 index dffc596f..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/dev_unix.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build !windows && !freebsd - -package archive - -import "golang.org/x/sys/unix" - -func mknod(path string, mode uint32, dev uint64) error { - return unix.Mknod(path, mode, int(dev)) -} diff --git a/vendor/github.com/docker/docker/pkg/archive/diff.go b/vendor/github.com/docker/docker/pkg/archive/diff.go index d5a394cd..e080e310 100644 --- a/vendor/github.com/docker/docker/pkg/archive/diff.go +++ b/vendor/github.com/docker/docker/pkg/archive/diff.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" @@ -11,6 +11,8 @@ import ( "strings" "github.com/containerd/log" + "github.com/docker/docker/pkg/pools" + "github.com/docker/docker/pkg/system" ) // UnpackLayer unpack `layer` to a `dest`. The stream `layer` can be @@ -18,6 +20,8 @@ import ( // Returns the size in bytes of the contents of the layer. func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, err error) { tr := tar.NewReader(layer) + trBuf := pools.BufioReader32KPool.Get(tr) + defer pools.BufioReader32KPool.Put(trBuf) var dirs []*tar.Header unpackedPaths := make(map[string]struct{}) @@ -156,7 +160,8 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, } } - srcData := io.Reader(tr) + trBuf.Reset(tr) + srcData := io.Reader(trBuf) srcHdr := hdr // Hard links into /.wh..wh.plnk don't work, as we don't extract that directory, so @@ -195,7 +200,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64, for _, hdr := range dirs { // #nosec G305 -- The header was checked for path traversal before it was appended to the dirs slice. path := filepath.Join(dest, hdr.Name) - if err := chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { + if err := system.Chtimes(path, hdr.AccessTime, hdr.ModTime); err != nil { return 0, err } } diff --git a/vendor/github.com/docker/docker/pkg/archive/time.go b/vendor/github.com/docker/docker/pkg/archive/time.go deleted file mode 100644 index 4e9ae950..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/time.go +++ /dev/null @@ -1,38 +0,0 @@ -package archive - -import ( - "syscall" - "time" - "unsafe" -) - -var ( - minTime = time.Unix(0, 0) - maxTime time.Time -) - -func init() { - if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 { - // This is a 64 bit timespec - // os.Chtimes limits time to the following - maxTime = time.Unix(0, 1<<63-1) - } else { - // This is a 32 bit timespec - maxTime = time.Unix(1<<31-1, 0) - } -} - -func boundTime(t time.Time) time.Time { - if t.Before(minTime) || t.After(maxTime) { - return minTime - } - - return t -} - -func latestTime(t1, t2 time.Time) time.Time { - if t1.Before(t2) { - return t2 - } - return t1 -} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_linux.go b/vendor/github.com/docker/docker/pkg/archive/time_linux.go new file mode 100644 index 00000000..797143ee --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/time_linux.go @@ -0,0 +1,16 @@ +package archive // import "github.com/docker/docker/pkg/archive" + +import ( + "syscall" + "time" +) + +func timeToTimespec(time time.Time) (ts syscall.Timespec) { + if time.IsZero() { + // Return UTIME_OMIT special value + ts.Sec = 0 + ts.Nsec = (1 << 30) - 2 + return + } + return syscall.NsecToTimespec(time.UnixNano()) +} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go b/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go deleted file mode 100644 index 8ce83bd0..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/time_nonwindows.go +++ /dev/null @@ -1,40 +0,0 @@ -//go:build !windows - -package archive - -import ( - "os" - "time" - - "golang.org/x/sys/unix" -) - -// chtimes changes the access time and modified time of a file at the given path. -// If the modified time is prior to the Unix Epoch (unixMinTime), or after the -// end of Unix Time (unixEpochTime), os.Chtimes has undefined behavior. In this -// case, Chtimes defaults to Unix Epoch, just in case. -func chtimes(name string, atime time.Time, mtime time.Time) error { - return os.Chtimes(name, atime, mtime) -} - -func timeToTimespec(time time.Time) (ts unix.Timespec) { - if time.IsZero() { - // Return UTIME_OMIT special value - ts.Sec = 0 - ts.Nsec = (1 << 30) - 2 - return - } - return unix.NsecToTimespec(time.UnixNano()) -} - -func lchtimes(name string, atime time.Time, mtime time.Time) error { - utimes := [2]unix.Timespec{ - timeToTimespec(atime), - timeToTimespec(mtime), - } - err := unix.UtimesNanoAt(unix.AT_FDCWD, name, utimes[0:], unix.AT_SYMLINK_NOFOLLOW) - if err != nil && err != unix.ENOSYS { - return err - } - return err -} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go new file mode 100644 index 00000000..14c4ceb1 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/archive/time_unsupported.go @@ -0,0 +1,16 @@ +//go:build !linux + +package archive // import "github.com/docker/docker/pkg/archive" + +import ( + "syscall" + "time" +) + +func timeToTimespec(time time.Time) (ts syscall.Timespec) { + nsec := int64(0) + if !time.IsZero() { + nsec = time.UnixNano() + } + return syscall.NsecToTimespec(nsec) +} diff --git a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go b/vendor/github.com/docker/docker/pkg/archive/whiteouts.go index d20478a1..4c072a87 100644 --- a/vendor/github.com/docker/docker/pkg/archive/whiteouts.go +++ b/vendor/github.com/docker/docker/pkg/archive/whiteouts.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" // Whiteouts are files with a special meaning for the layered filesystem. // Docker uses AUFS whiteout files inside exported archives. In other diff --git a/vendor/github.com/docker/docker/pkg/archive/wrap.go b/vendor/github.com/docker/docker/pkg/archive/wrap.go index 903befd7..032db82c 100644 --- a/vendor/github.com/docker/docker/pkg/archive/wrap.go +++ b/vendor/github.com/docker/docker/pkg/archive/wrap.go @@ -1,4 +1,4 @@ -package archive +package archive // import "github.com/docker/docker/pkg/archive" import ( "archive/tar" diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go deleted file mode 100644 index 652a1f0f..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build linux || darwin || freebsd || netbsd - -package archive - -import ( - "errors" - "fmt" - "io/fs" - - "golang.org/x/sys/unix" -) - -// lgetxattr retrieves the value of the extended attribute identified by attr -// and associated with the given path in the file system. -// It returns a nil slice and nil error if the xattr is not set. -func lgetxattr(path string, attr string) ([]byte, error) { - // Start with a 128 length byte array - dest := make([]byte, 128) - sz, err := unix.Lgetxattr(path, attr, dest) - - for errors.Is(err, unix.ERANGE) { - // Buffer too small, use zero-sized buffer to get the actual size - sz, err = unix.Lgetxattr(path, attr, []byte{}) - if err != nil { - return nil, wrapPathError("lgetxattr", path, attr, err) - } - dest = make([]byte, sz) - sz, err = unix.Lgetxattr(path, attr, dest) - } - - if err != nil { - if errors.Is(err, noattr) { - return nil, nil - } - return nil, wrapPathError("lgetxattr", path, attr, err) - } - - return dest[:sz], nil -} - -// lsetxattr sets the value of the extended attribute identified by attr -// and associated with the given path in the file system. -func lsetxattr(path string, attr string, data []byte, flags int) error { - return wrapPathError("lsetxattr", path, attr, unix.Lsetxattr(path, attr, data, flags)) -} - -func wrapPathError(op, path, attr string, err error) error { - if err == nil { - return nil - } - return &fs.PathError{Op: op, Path: path, Err: fmt.Errorf("xattr %q: %w", attr, err)} -} diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go deleted file mode 100644 index f2e76465..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_linux.go +++ /dev/null @@ -1,5 +0,0 @@ -package archive - -import "golang.org/x/sys/unix" - -var noattr = unix.ENODATA diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go b/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go deleted file mode 100644 index 4d882415..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/xattr_supported_unix.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !linux && !windows - -package archive - -import "golang.org/x/sys/unix" - -var noattr = unix.ENOATTR diff --git a/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go b/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go deleted file mode 100644 index b0d9165c..00000000 --- a/vendor/github.com/docker/docker/pkg/archive/xattr_unsupported.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !linux && !darwin && !freebsd && !netbsd - -package archive - -func lgetxattr(path string, attr string) ([]byte, error) { - return nil, nil -} - -func lsetxattr(path string, attr string, data []byte, flags int) error { - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools.go b/vendor/github.com/docker/docker/pkg/idtools/idtools.go index d2fbd943..79d682c6 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools.go @@ -1,8 +1,11 @@ -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( + "bufio" "fmt" "os" + "strconv" + "strings" ) // IDMap contains a single entry for user namespace range remapping. An array @@ -14,6 +17,22 @@ type IDMap struct { Size int `json:"size"` } +type subIDRange struct { + Start int + Length int +} + +type ranges []subIDRange + +func (e ranges) Len() int { return len(e) } +func (e ranges) Swap(i, j int) { e[i], e[j] = e[j], e[i] } +func (e ranges) Less(i, j int) bool { return e[i].Start < e[j].Start } + +const ( + subuidFileName = "/etc/subuid" + subgidFileName = "/etc/subgid" +) + // MkdirAllAndChown creates a directory (include any along the path) and then modifies // ownership to the requested uid/gid. If the directory already exists, this // function will still change ownership and permissions. @@ -143,6 +162,67 @@ func (i IdentityMapping) Empty() bool { return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0 } +func createIDMap(subidRanges ranges) []IDMap { + idMap := []IDMap{} + + containerID := 0 + for _, idrange := range subidRanges { + idMap = append(idMap, IDMap{ + ContainerID: containerID, + HostID: idrange.Start, + Size: idrange.Length, + }) + containerID = containerID + idrange.Length + } + return idMap +} + +func parseSubuid(username string) (ranges, error) { + return parseSubidFile(subuidFileName, username) +} + +func parseSubgid(username string) (ranges, error) { + return parseSubidFile(subgidFileName, username) +} + +// parseSubidFile will read the appropriate file (/etc/subuid or /etc/subgid) +// and return all found ranges for a specified username. If the special value +// "ALL" is supplied for username, then all ranges in the file will be returned +func parseSubidFile(path, username string) (ranges, error) { + var rangeList ranges + + subidFile, err := os.Open(path) + if err != nil { + return rangeList, err + } + defer subidFile.Close() + + s := bufio.NewScanner(subidFile) + for s.Scan() { + text := strings.TrimSpace(s.Text()) + if text == "" || strings.HasPrefix(text, "#") { + continue + } + parts := strings.Split(text, ":") + if len(parts) != 3 { + return rangeList, fmt.Errorf("Cannot parse subuid/gid information: Format not correct for %s file", path) + } + if parts[0] == username || username == "ALL" { + startid, err := strconv.Atoi(parts[1]) + if err != nil { + return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) + } + length, err := strconv.Atoi(parts[2]) + if err != nil { + return rangeList, fmt.Errorf("String to int conversion failed during subuid/gid parsing of %s: %v", path, err) + } + rangeList = append(rangeList, subIDRange{startid, length}) + } + } + + return rangeList, s.Err() +} + // CurrentIdentity returns the identity of the current process func CurrentIdentity() Identity { return Identity{UID: os.Getuid(), GID: os.Getegid()} diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go index 1f11fe47..cd621bdc 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_unix.go @@ -1,10 +1,13 @@ //go:build !windows -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( + "bytes" "fmt" + "io" "os" + "os/exec" "path/filepath" "strconv" "syscall" @@ -69,25 +72,127 @@ func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting return nil } -// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username -// -// Deprecated: use [user.LookupUser] instead +// LookupUser uses traditional local system files lookup (from libcontainer/user) on a username, +// followed by a call to `getent` for supporting host configured non-files passwd and group dbs func LookupUser(name string) (user.User, error) { - return user.LookupUser(name) + // first try a local system files lookup using existing capabilities + usr, err := user.LookupUser(name) + if err == nil { + return usr, nil + } + // local files lookup failed; attempt to call `getent` to query configured passwd dbs + usr, err = getentUser(name) + if err != nil { + return user.User{}, err + } + return usr, nil } -// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid -// -// Deprecated: use [user.LookupUid] instead +// LookupUID uses traditional local system files lookup (from libcontainer/user) on a uid, +// followed by a call to `getent` for supporting host configured non-files passwd and group dbs func LookupUID(uid int) (user.User, error) { - return user.LookupUid(uid) + // first try a local system files lookup using existing capabilities + usr, err := user.LookupUid(uid) + if err == nil { + return usr, nil + } + // local files lookup failed; attempt to call `getent` to query configured passwd dbs + return getentUser(strconv.Itoa(uid)) +} + +func getentUser(name string) (user.User, error) { + reader, err := callGetent("passwd", name) + if err != nil { + return user.User{}, err + } + users, err := user.ParsePasswd(reader) + if err != nil { + return user.User{}, err + } + if len(users) == 0 { + return user.User{}, fmt.Errorf("getent failed to find passwd entry for %q", name) + } + return users[0], nil } // LookupGroup uses traditional local system files lookup (from libcontainer/user) on a group name, -// -// Deprecated: use [user.LookupGroup] instead +// followed by a call to `getent` for supporting host configured non-files passwd and group dbs func LookupGroup(name string) (user.Group, error) { - return user.LookupGroup(name) + // first try a local system files lookup using existing capabilities + group, err := user.LookupGroup(name) + if err == nil { + return group, nil + } + // local files lookup failed; attempt to call `getent` to query configured group dbs + return getentGroup(name) +} + +// LookupGID uses traditional local system files lookup (from libcontainer/user) on a group ID, +// followed by a call to `getent` for supporting host configured non-files passwd and group dbs +func LookupGID(gid int) (user.Group, error) { + // first try a local system files lookup using existing capabilities + group, err := user.LookupGid(gid) + if err == nil { + return group, nil + } + // local files lookup failed; attempt to call `getent` to query configured group dbs + return getentGroup(strconv.Itoa(gid)) +} + +func getentGroup(name string) (user.Group, error) { + reader, err := callGetent("group", name) + if err != nil { + return user.Group{}, err + } + groups, err := user.ParseGroup(reader) + if err != nil { + return user.Group{}, err + } + if len(groups) == 0 { + return user.Group{}, fmt.Errorf("getent failed to find groups entry for %q", name) + } + return groups[0], nil +} + +func callGetent(database, key string) (io.Reader, error) { + getentCmd, err := resolveBinary("getent") + // if no `getent` command within the execution environment, can't do anything else + if err != nil { + return nil, fmt.Errorf("unable to find getent command: %w", err) + } + command := exec.Command(getentCmd, database, key) + // we run getent within container filesystem, but without /dev so /dev/null is not available for exec to mock stdin + command.Stdin = io.NopCloser(bytes.NewReader(nil)) + out, err := command.CombinedOutput() + if err != nil { + exitCode, errC := getExitCode(err) + if errC != nil { + return nil, err + } + switch exitCode { + case 1: + return nil, fmt.Errorf("getent reported invalid parameters/database unknown") + case 2: + return nil, fmt.Errorf("getent unable to find entry %q in %s database", key, database) + case 3: + return nil, fmt.Errorf("getent database doesn't support enumeration") + default: + return nil, err + } + } + return bytes.NewReader(out), nil +} + +// getExitCode returns the ExitStatus of the specified error if its type is +// exec.ExitError, returns 0 and an error otherwise. +func getExitCode(err error) (int, error) { + exitCode := 0 + if exiterr, ok := err.(*exec.ExitError); ok { + if procExit, ok := exiterr.Sys().(syscall.WaitStatus); ok { + return procExit.ExitStatus(), nil + } + } + return exitCode, fmt.Errorf("failed to get exit code") } // setPermissions performs a chown/chmod only if the uid/gid don't match what's requested @@ -118,17 +223,16 @@ func setPermissions(p string, mode os.FileMode, owner Identity, stat os.FileInfo // using the data from /etc/sub{uid,gid} ranges, creates the // proper uid and gid remapping ranges for that user/group pair func LoadIdentityMapping(name string) (IdentityMapping, error) { - // TODO: Consider adding support for calling out to "getent" - usr, err := user.LookupUser(name) + usr, err := LookupUser(name) if err != nil { return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %v", name, err) } - subuidRanges, err := lookupSubRangesFile("/etc/subuid", usr) + subuidRanges, err := lookupSubUIDRanges(usr) if err != nil { return IdentityMapping{}, err } - subgidRanges, err := lookupSubRangesFile("/etc/subgid", usr) + subgidRanges, err := lookupSubGIDRanges(usr) if err != nil { return IdentityMapping{}, err } @@ -139,28 +243,36 @@ func LoadIdentityMapping(name string) (IdentityMapping, error) { }, nil } -func lookupSubRangesFile(path string, usr user.User) ([]IDMap, error) { - uidstr := strconv.Itoa(usr.Uid) - rangeList, err := user.ParseSubIDFileFilter(path, func(sid user.SubID) bool { - return sid.Name == usr.Name || sid.Name == uidstr - }) +func lookupSubUIDRanges(usr user.User) ([]IDMap, error) { + rangeList, err := parseSubuid(strconv.Itoa(usr.Uid)) if err != nil { return nil, err } + if len(rangeList) == 0 { + rangeList, err = parseSubuid(usr.Name) + if err != nil { + return nil, err + } + } if len(rangeList) == 0 { return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name) } - - idMap := []IDMap{} - - containerID := 0 - for _, idrange := range rangeList { - idMap = append(idMap, IDMap{ - ContainerID: containerID, - HostID: int(idrange.SubID), - Size: int(idrange.Count), - }) - containerID = containerID + int(idrange.Count) - } - return idMap, nil + return createIDMap(rangeList), nil +} + +func lookupSubGIDRanges(usr user.User) ([]IDMap, error) { + rangeList, err := parseSubgid(strconv.Itoa(usr.Uid)) + if err != nil { + return nil, err + } + if len(rangeList) == 0 { + rangeList, err = parseSubgid(usr.Name) + if err != nil { + return nil, err + } + } + if len(rangeList) == 0 { + return nil, fmt.Errorf("no subgid ranges found for user %q", usr.Name) + } + return createIDMap(rangeList), nil } diff --git a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go index a12b1404..32953f45 100644 --- a/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go +++ b/vendor/github.com/docker/docker/pkg/idtools/idtools_windows.go @@ -1,24 +1,24 @@ -package idtools +package idtools // import "github.com/docker/docker/pkg/idtools" import ( "os" + + "github.com/docker/docker/pkg/system" ) const ( SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege" ) -// TODO(thaJeztah): these magic consts need a source of reference, and should be defined in a canonical location const ( ContainerAdministratorSidString = "S-1-5-93-2-1" - - ContainerUserSidString = "S-1-5-93-2-2" + ContainerUserSidString = "S-1-5-93-2-2" ) -// This is currently a wrapper around [os.MkdirAll] since currently +// This is currently a wrapper around MkdirAll, however, since currently // permissions aren't set through this path, the identity isn't utilized. // Ownership is handled elsewhere, but in the future could be support here // too. func mkdirAs(path string, _ os.FileMode, _ Identity, _, _ bool) error { - return os.MkdirAll(path, 0) + return system.MkdirAll(path, 0) } diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go new file mode 100644 index 00000000..f0c075e2 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_linux.go @@ -0,0 +1,166 @@ +package idtools // import "github.com/docker/docker/pkg/idtools" + +import ( + "fmt" + "os/exec" + "regexp" + "sort" + "strconv" + "strings" + "sync" +) + +// add a user and/or group to Linux /etc/passwd, /etc/group using standard +// Linux distribution commands: +// adduser --system --shell /bin/false --disabled-login --disabled-password --no-create-home --group +// useradd -r -s /bin/false + +var ( + once sync.Once + userCommand string + idOutRegexp = regexp.MustCompile(`uid=([0-9]+).*gid=([0-9]+)`) +) + +const ( + // default length for a UID/GID subordinate range + defaultRangeLen = 65536 + defaultRangeStart = 100000 +) + +// AddNamespaceRangesUser takes a username and uses the standard system +// utility to create a system user/group pair used to hold the +// /etc/sub{uid,gid} ranges which will be used for user namespace +// mapping ranges in containers. +func AddNamespaceRangesUser(name string) (int, int, error) { + if err := addUser(name); err != nil { + return -1, -1, fmt.Errorf("error adding user %q: %v", name, err) + } + + // Query the system for the created uid and gid pair + out, err := exec.Command("id", name).CombinedOutput() + if err != nil { + return -1, -1, fmt.Errorf("error trying to find uid/gid for new user %q: %v", name, err) + } + matches := idOutRegexp.FindStringSubmatch(strings.TrimSpace(string(out))) + if len(matches) != 3 { + return -1, -1, fmt.Errorf("can't find uid, gid from `id` output: %q", string(out)) + } + uid, err := strconv.Atoi(matches[1]) + if err != nil { + return -1, -1, fmt.Errorf("can't convert found uid (%s) to int: %v", matches[1], err) + } + gid, err := strconv.Atoi(matches[2]) + if err != nil { + return -1, -1, fmt.Errorf("Can't convert found gid (%s) to int: %v", matches[2], err) + } + + // Now we need to create the subuid/subgid ranges for our new user/group (system users + // do not get auto-created ranges in subuid/subgid) + + if err := createSubordinateRanges(name); err != nil { + return -1, -1, fmt.Errorf("couldn't create subordinate ID ranges: %v", err) + } + return uid, gid, nil +} + +func addUser(name string) error { + once.Do(func() { + // set up which commands are used for adding users/groups dependent on distro + if _, err := resolveBinary("adduser"); err == nil { + userCommand = "adduser" + } else if _, err := resolveBinary("useradd"); err == nil { + userCommand = "useradd" + } + }) + var args []string + switch userCommand { + case "adduser": + args = []string{"--system", "--shell", "/bin/false", "--no-create-home", "--disabled-login", "--disabled-password", "--group", name} + case "useradd": + args = []string{"-r", "-s", "/bin/false", name} + default: + return fmt.Errorf("cannot add user; no useradd/adduser binary found") + } + + if out, err := exec.Command(userCommand, args...).CombinedOutput(); err != nil { + return fmt.Errorf("failed to add user with error: %v; output: %q", err, string(out)) + } + return nil +} + +func createSubordinateRanges(name string) error { + // first, we should verify that ranges weren't automatically created + // by the distro tooling + ranges, err := parseSubuid(name) + if err != nil { + return fmt.Errorf("error while looking for subuid ranges for user %q: %v", name, err) + } + if len(ranges) == 0 { + // no UID ranges; let's create one + startID, err := findNextUIDRange() + if err != nil { + return fmt.Errorf("can't find available subuid range: %v", err) + } + idRange := fmt.Sprintf("%d-%d", startID, startID+defaultRangeLen-1) + out, err := exec.Command("usermod", "-v", idRange, name).CombinedOutput() + if err != nil { + return fmt.Errorf("unable to add subuid range to user: %q; output: %s, err: %v", name, out, err) + } + } + + ranges, err = parseSubgid(name) + if err != nil { + return fmt.Errorf("error while looking for subgid ranges for user %q: %v", name, err) + } + if len(ranges) == 0 { + // no GID ranges; let's create one + startID, err := findNextGIDRange() + if err != nil { + return fmt.Errorf("can't find available subgid range: %v", err) + } + idRange := fmt.Sprintf("%d-%d", startID, startID+defaultRangeLen-1) + out, err := exec.Command("usermod", "-w", idRange, name).CombinedOutput() + if err != nil { + return fmt.Errorf("unable to add subgid range to user: %q; output: %s, err: %v", name, out, err) + } + } + return nil +} + +func findNextUIDRange() (int, error) { + ranges, err := parseSubuid("ALL") + if err != nil { + return -1, fmt.Errorf("couldn't parse all ranges in /etc/subuid file: %v", err) + } + sort.Sort(ranges) + return findNextRangeStart(ranges) +} + +func findNextGIDRange() (int, error) { + ranges, err := parseSubgid("ALL") + if err != nil { + return -1, fmt.Errorf("couldn't parse all ranges in /etc/subgid file: %v", err) + } + sort.Sort(ranges) + return findNextRangeStart(ranges) +} + +func findNextRangeStart(rangeList ranges) (int, error) { + startID := defaultRangeStart + for _, arange := range rangeList { + if wouldOverlap(arange, startID) { + startID = arange.Start + arange.Length + } + } + return startID, nil +} + +func wouldOverlap(arange subIDRange, ID int) bool { + low := ID + high := ID + defaultRangeLen + if (low >= arange.Start && low <= arange.Start+arange.Length) || + (high <= arange.Start+arange.Length && high >= arange.Start) { + return true + } + return false +} diff --git a/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go new file mode 100644 index 00000000..6a9311c4 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/idtools/usergroupadd_unsupported.go @@ -0,0 +1,12 @@ +//go:build !linux + +package idtools // import "github.com/docker/docker/pkg/idtools" + +import "fmt" + +// AddNamespaceRangesUser takes a name and finds an unused uid, gid pair +// and calls the appropriate helper function to add the group and then +// the user to the group in /etc/group and /etc/passwd respectively. +func AddNamespaceRangesUser(name string) (int, int, error) { + return -1, -1, fmt.Errorf("No support for adding users or groups on this OS") +} diff --git a/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go b/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go new file mode 100644 index 00000000..517a2f52 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/idtools/utils_unix.go @@ -0,0 +1,26 @@ +//go:build !windows + +package idtools // import "github.com/docker/docker/pkg/idtools" + +import ( + "fmt" + "os/exec" + "path/filepath" +) + +func resolveBinary(binname string) (string, error) { + binaryPath, err := exec.LookPath(binname) + if err != nil { + return "", err + } + resolvedPath, err := filepath.EvalSymlinks(binaryPath) + if err != nil { + return "", err + } + // only return no error if the final resolved binary basename + // matches what was searched for + if filepath.Base(resolvedPath) == binname { + return resolvedPath, nil + } + return "", fmt.Errorf("Binary %q does not resolve to a binary of that name in $PATH (%q)", binname, resolvedPath) +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/buffer.go b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go new file mode 100644 index 00000000..466f7929 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/buffer.go @@ -0,0 +1,51 @@ +package ioutils // import "github.com/docker/docker/pkg/ioutils" + +import ( + "errors" + "io" +) + +var errBufferFull = errors.New("buffer is full") + +type fixedBuffer struct { + buf []byte + pos int + lastRead int +} + +func (b *fixedBuffer) Write(p []byte) (int, error) { + n := copy(b.buf[b.pos:cap(b.buf)], p) + b.pos += n + + if n < len(p) { + if b.pos == cap(b.buf) { + return n, errBufferFull + } + return n, io.ErrShortWrite + } + return n, nil +} + +func (b *fixedBuffer) Read(p []byte) (int, error) { + n := copy(p, b.buf[b.lastRead:b.pos]) + b.lastRead += n + return n, nil +} + +func (b *fixedBuffer) Len() int { + return b.pos - b.lastRead +} + +func (b *fixedBuffer) Cap() int { + return cap(b.buf) +} + +func (b *fixedBuffer) Reset() { + b.pos = 0 + b.lastRead = 0 + b.buf = b.buf[:0] +} + +func (b *fixedBuffer) String() string { + return string(b.buf[b.lastRead:b.pos]) +} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go new file mode 100644 index 00000000..85450bf6 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/ioutils/bytespipe.go @@ -0,0 +1,193 @@ +package ioutils // import "github.com/docker/docker/pkg/ioutils" + +import ( + "errors" + "io" + "sync" +) + +// maxCap is the highest capacity to use in byte slices that buffer data. +const maxCap = 1e6 + +// minCap is the lowest capacity to use in byte slices that buffer data +const minCap = 64 + +// blockThreshold is the minimum number of bytes in the buffer which will cause +// a write to BytesPipe to block when allocating a new slice. +const blockThreshold = 1e6 + +var ( + // ErrClosed is returned when Write is called on a closed BytesPipe. + // + // Deprecated: this type is only used internally, and will be removed in the next release. + ErrClosed = errors.New("write to closed BytesPipe") + + bufPools = make(map[int]*sync.Pool) + bufPoolsLock sync.Mutex +) + +// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue). +// All written data may be read at most once. Also, BytesPipe allocates +// and releases new byte slices to adjust to current needs, so the buffer +// won't be overgrown after peak loads. +// +// Deprecated: this type is only used internally, and will be removed in the next release. +type BytesPipe struct { + mu sync.Mutex + wait *sync.Cond + buf []*fixedBuffer + bufLen int + closeErr error // error to return from next Read. set to nil if not closed. + readBlock bool // check read BytesPipe is Wait() or not +} + +// NewBytesPipe creates new BytesPipe, initialized by specified slice. +// If buf is nil, then it will be initialized with slice which cap is 64. +// buf will be adjusted in a way that len(buf) == 0, cap(buf) == cap(buf). +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func NewBytesPipe() *BytesPipe { + bp := &BytesPipe{} + bp.buf = append(bp.buf, getBuffer(minCap)) + bp.wait = sync.NewCond(&bp.mu) + return bp +} + +// Write writes p to BytesPipe. +// It can allocate new []byte slices in a process of writing. +func (bp *BytesPipe) Write(p []byte) (int, error) { + bp.mu.Lock() + defer bp.mu.Unlock() + + written := 0 +loop0: + for { + if bp.closeErr != nil { + return written, ErrClosed + } + + if len(bp.buf) == 0 { + bp.buf = append(bp.buf, getBuffer(64)) + } + // get the last buffer + b := bp.buf[len(bp.buf)-1] + + n, err := b.Write(p) + written += n + bp.bufLen += n + + // errBufferFull is an error we expect to get if the buffer is full + if err != nil && err != errBufferFull { + bp.wait.Broadcast() + return written, err + } + + // if there was enough room to write all then break + if len(p) == n { + break + } + + // more data: write to the next slice + p = p[n:] + + // make sure the buffer doesn't grow too big from this write + for bp.bufLen >= blockThreshold { + if bp.readBlock { + bp.wait.Broadcast() + } + bp.wait.Wait() + if bp.closeErr != nil { + continue loop0 + } + } + + // add new byte slice to the buffers slice and continue writing + nextCap := b.Cap() * 2 + if nextCap > maxCap { + nextCap = maxCap + } + bp.buf = append(bp.buf, getBuffer(nextCap)) + } + bp.wait.Broadcast() + return written, nil +} + +// CloseWithError causes further reads from a BytesPipe to return immediately. +func (bp *BytesPipe) CloseWithError(err error) error { + bp.mu.Lock() + if err != nil { + bp.closeErr = err + } else { + bp.closeErr = io.EOF + } + bp.wait.Broadcast() + bp.mu.Unlock() + return nil +} + +// Close causes further reads from a BytesPipe to return immediately. +func (bp *BytesPipe) Close() error { + return bp.CloseWithError(nil) +} + +// Read reads bytes from BytesPipe. +// Data could be read only once. +func (bp *BytesPipe) Read(p []byte) (n int, err error) { + bp.mu.Lock() + defer bp.mu.Unlock() + if bp.bufLen == 0 { + if bp.closeErr != nil { + return 0, bp.closeErr + } + bp.readBlock = true + bp.wait.Wait() + bp.readBlock = false + if bp.bufLen == 0 && bp.closeErr != nil { + return 0, bp.closeErr + } + } + + for bp.bufLen > 0 { + b := bp.buf[0] + read, _ := b.Read(p) // ignore error since fixedBuffer doesn't really return an error + n += read + bp.bufLen -= read + + if b.Len() == 0 { + // it's empty so return it to the pool and move to the next one + returnBuffer(b) + bp.buf[0] = nil + bp.buf = bp.buf[1:] + } + + if len(p) == read { + break + } + + p = p[read:] + } + + bp.wait.Broadcast() + return +} + +func returnBuffer(b *fixedBuffer) { + b.Reset() + bufPoolsLock.Lock() + pool := bufPools[b.Cap()] + bufPoolsLock.Unlock() + if pool != nil { + pool.Put(b) + } +} + +func getBuffer(size int) *fixedBuffer { + bufPoolsLock.Lock() + pool, ok := bufPools[size] + if !ok { + pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }} + bufPools[size] = pool + } + bufPoolsLock.Unlock() + return pool.Get().(*fixedBuffer) +} diff --git a/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go similarity index 74% rename from vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go rename to vendor/github.com/docker/docker/pkg/ioutils/fswriters.go index cbbe835b..05da97b0 100644 --- a/vendor/github.com/docker/docker/pkg/atomicwriter/atomicwriter.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/fswriters.go @@ -1,4 +1,4 @@ -package atomicwriter +package ioutils // import "github.com/docker/docker/pkg/ioutils" import ( "io" @@ -6,11 +6,11 @@ import ( "path/filepath" ) -// New returns a WriteCloser so that writing to it writes to a +// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a // temporary file and closing it atomically changes the temporary file to // destination path. Writing and closing concurrently is not allowed. // NOTE: umask is not considered for the file's permissions. -func New(filename string, perm os.FileMode) (io.WriteCloser, error) { +func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { f, err := os.CreateTemp(filepath.Dir(filename), ".tmp-"+filepath.Base(filename)) if err != nil { return nil, err @@ -27,10 +27,10 @@ func New(filename string, perm os.FileMode) (io.WriteCloser, error) { }, nil } -// WriteFile atomically writes data to a file named by filename and with the specified permission bits. +// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. // NOTE: umask is not considered for the file's permissions. -func WriteFile(filename string, data []byte, perm os.FileMode) error { - f, err := New(filename, perm) +func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { + f, err := NewAtomicFileWriter(filename, perm) if err != nil { return err } @@ -82,32 +82,32 @@ func (w *atomicFileWriter) Close() (retErr error) { return nil } -// WriteSet is used to atomically write a set +// AtomicWriteSet is used to atomically write a set // of files and ensure they are visible at the same time. // Must be committed to a new directory. -type WriteSet struct { +type AtomicWriteSet struct { root string } -// NewWriteSet creates a new atomic write set to +// NewAtomicWriteSet creates a new atomic write set to // atomically create a set of files. The given directory // is used as the base directory for storing files before // commit. If no temporary directory is given the system // default is used. -func NewWriteSet(tmpDir string) (*WriteSet, error) { +func NewAtomicWriteSet(tmpDir string) (*AtomicWriteSet, error) { td, err := os.MkdirTemp(tmpDir, "write-set-") if err != nil { return nil, err } - return &WriteSet{ + return &AtomicWriteSet{ root: td, }, nil } // WriteFile writes a file to the set, guaranteeing the file // has been synced. -func (ws *WriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { +func (ws *AtomicWriteSet) WriteFile(filename string, data []byte, perm os.FileMode) error { f, err := ws.FileWriter(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return err @@ -136,7 +136,7 @@ func (w syncFileCloser) Close() error { // FileWriter opens a file writer inside the set. The file // should be synced and closed before calling commit. -func (ws *WriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { +func (ws *AtomicWriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.WriteCloser, error) { f, err := os.OpenFile(filepath.Join(ws.root, name), flag, perm) if err != nil { return nil, err @@ -146,18 +146,18 @@ func (ws *WriteSet) FileWriter(name string, flag int, perm os.FileMode) (io.Writ // Cancel cancels the set and removes all temporary data // created in the set. -func (ws *WriteSet) Cancel() error { +func (ws *AtomicWriteSet) Cancel() error { return os.RemoveAll(ws.root) } // Commit moves all created files to the target directory. The // target directory must not exist and the parent of the target // directory must exist. -func (ws *WriteSet) Commit(target string) error { +func (ws *AtomicWriteSet) Commit(target string) error { return os.Rename(ws.root, target) } // String returns the location the set is writing to. -func (ws *WriteSet) String() string { +func (ws *AtomicWriteSet) String() string { return ws.root } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go b/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go deleted file mode 100644 index c3cee16d..00000000 --- a/vendor/github.com/docker/docker/pkg/ioutils/fswriters_deprecated.go +++ /dev/null @@ -1,44 +0,0 @@ -package ioutils - -import ( - "io" - "os" - - "github.com/docker/docker/pkg/atomicwriter" -) - -// NewAtomicFileWriter returns WriteCloser so that writing to it writes to a -// temporary file and closing it atomically changes the temporary file to -// destination path. Writing and closing concurrently is not allowed. -// NOTE: umask is not considered for the file's permissions. -// -// Deprecated: use [atomicwriter.New] instead. -func NewAtomicFileWriter(filename string, perm os.FileMode) (io.WriteCloser, error) { - return atomicwriter.New(filename, perm) -} - -// AtomicWriteFile atomically writes data to a file named by filename and with the specified permission bits. -// NOTE: umask is not considered for the file's permissions. -// -// Deprecated: use [atomicwriter.WriteFile] instead. -func AtomicWriteFile(filename string, data []byte, perm os.FileMode) error { - return atomicwriter.WriteFile(filename, data, perm) -} - -// AtomicWriteSet is used to atomically write a set -// of files and ensure they are visible at the same time. -// Must be committed to a new directory. -// -// Deprecated: use [atomicwriter.WriteSet] instead. -type AtomicWriteSet = atomicwriter.WriteSet - -// NewAtomicWriteSet creates a new atomic write set to -// atomically create a set of files. The given directory -// is used as the base directory for storing files before -// commit. If no temporary directory is given the system -// default is used. -// -// Deprecated: use [atomicwriter.NewWriteSet] instead. -func NewAtomicWriteSet(tmpDir string) (*atomicwriter.WriteSet, error) { - return atomicwriter.NewWriteSet(tmpDir) -} diff --git a/vendor/github.com/docker/docker/pkg/ioutils/readers.go b/vendor/github.com/docker/docker/pkg/ioutils/readers.go index 9ddba246..e03d3fee 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/readers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/readers.go @@ -6,20 +6,25 @@ import ( "runtime/debug" "sync/atomic" + // make sure crypto.SHA256, crypto.sha512 and crypto.SHA384 are registered + // TODO remove once https://github.com/opencontainers/go-digest/pull/64 is merged. + _ "crypto/sha256" + _ "crypto/sha512" + "github.com/containerd/log" ) -// readCloserWrapper wraps an io.Reader, and implements an io.ReadCloser +// ReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser // It calls the given callback function when closed. It should be constructed // with NewReadCloserWrapper -type readCloserWrapper struct { +type ReadCloserWrapper struct { io.Reader closer func() error closed atomic.Bool } // 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 @@ -27,15 +32,64 @@ func (r *readCloserWrapper) Close() error { return r.closer() } -// NewReadCloserWrapper wraps an io.Reader, and implements an io.ReadCloser. -// It calls the given callback function when closed. +// NewReadCloserWrapper returns a new io.ReadCloser. func NewReadCloserWrapper(r io.Reader, closer func() error) io.ReadCloser { - return &readCloserWrapper{ + return &ReadCloserWrapper{ Reader: r, closer: closer, } } +type readerErrWrapper struct { + reader io.Reader + closer func() +} + +func (r *readerErrWrapper) Read(p []byte) (int, error) { + n, err := r.reader.Read(p) + if err != nil { + r.closer() + } + return n, err +} + +// NewReaderErrWrapper returns a new io.Reader. +func NewReaderErrWrapper(r io.Reader, closer func()) io.Reader { + return &readerErrWrapper{ + reader: r, + closer: closer, + } +} + +// OnEOFReader wraps an io.ReadCloser and a function +// the function will run at the end of file or close the file. +type OnEOFReader struct { + Rc io.ReadCloser + Fn func() +} + +func (r *OnEOFReader) Read(p []byte) (n int, err error) { + n, err = r.Rc.Read(p) + if err == io.EOF { + r.runFunc() + } + return +} + +// Close closes the file and run the function. +func (r *OnEOFReader) Close() error { + err := r.Rc.Close() + r.runFunc() + return err +} + +func (r *OnEOFReader) runFunc() { + if fn := r.Fn; fn != nil { + fn() + r.Fn = nil + } +} + // cancelReadCloser wraps an io.ReadCloser with a context for cancelling read // operations. type cancelReadCloser struct { diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go index 010db59f..d8a8893f 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writeflusher.go @@ -21,10 +21,12 @@ type flusher interface { Flush() } +var errWriteFlusherClosed = io.EOF + func (wf *WriteFlusher) Write(b []byte) (n int, err error) { select { case <-wf.closed: - return 0, io.EOF + return 0, errWriteFlusherClosed default: } @@ -71,7 +73,7 @@ func (wf *WriteFlusher) Close() error { select { case <-wf.closed: - return io.EOF + return errWriteFlusherClosed default: close(wf.closed) } diff --git a/vendor/github.com/docker/docker/pkg/ioutils/writers.go b/vendor/github.com/docker/docker/pkg/ioutils/writers.go index 9c2d5d3b..aec8b4c0 100644 --- a/vendor/github.com/docker/docker/pkg/ioutils/writers.go +++ b/vendor/github.com/docker/docker/pkg/ioutils/writers.go @@ -5,6 +5,33 @@ import ( "sync/atomic" ) +// NopWriter represents a type which write operation is nop. +// +// Deprecated: use [io.Discard] instead. This type will be removed in the next release. +type NopWriter struct{} + +func (*NopWriter) Write(buf []byte) (int, error) { + return len(buf), nil +} + +type nopWriteCloser struct { + io.Writer +} + +func (w *nopWriteCloser) Close() error { return nil } + +// NopWriteCloser returns a nopWriteCloser. +// +// Deprecated: This function is no longer used and will be removed in the next release. +func NopWriteCloser(w io.Writer) io.WriteCloser { + return &nopWriteCloser{w} +} + +// NopFlusher represents a type which flush operation is nop. +// +// Deprecated: NopFlusher is only used internally and will be removed in the next release. +type NopFlusher = nopFlusher + type writeCloserWrapper struct { io.Writer closer func() error @@ -26,3 +53,29 @@ func NewWriteCloserWrapper(r io.Writer, closer func() error) io.WriteCloser { closer: closer, } } + +// WriteCounter wraps a concrete io.Writer and hold a count of the number +// of bytes written to the writer during a "session". +// This can be convenient when write return is masked +// (e.g., json.Encoder.Encode()) +// +// Deprecated: this type is no longer used and will be removed in the next release. +type WriteCounter struct { + Count int64 + Writer io.Writer +} + +// NewWriteCounter returns a new WriteCounter. +// +// Deprecated: this function is no longer used and will be removed in the next release. +func NewWriteCounter(w io.Writer) *WriteCounter { + return &WriteCounter{ + Writer: w, + } +} + +func (wc *WriteCounter) Write(p []byte) (count int, err error) { + count, err = wc.Writer.Write(p) + wc.Count += int64(count) + return +} diff --git a/vendor/github.com/docker/docker/pkg/pools/pools.go b/vendor/github.com/docker/docker/pkg/pools/pools.go new file mode 100644 index 00000000..3ea3012b --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/pools/pools.go @@ -0,0 +1,137 @@ +// Package pools provides a collection of pools which provide various +// data types with buffers. These can be used to lower the number of +// memory allocations and reuse buffers. +// +// New pools should be added to this package to allow them to be +// shared across packages. +// +// Utility functions which operate on pools should be added to this +// package to allow them to be reused. +package pools // import "github.com/docker/docker/pkg/pools" + +import ( + "bufio" + "io" + "sync" + + "github.com/docker/docker/pkg/ioutils" +) + +const buffer32K = 32 * 1024 + +var ( + // BufioReader32KPool is a pool which returns bufio.Reader with a 32K buffer. + BufioReader32KPool = newBufioReaderPoolWithSize(buffer32K) + // BufioWriter32KPool is a pool which returns bufio.Writer with a 32K buffer. + BufioWriter32KPool = newBufioWriterPoolWithSize(buffer32K) + buffer32KPool = newBufferPoolWithSize(buffer32K) +) + +// BufioReaderPool is a bufio reader that uses sync.Pool. +type BufioReaderPool struct { + pool sync.Pool +} + +// newBufioReaderPoolWithSize is unexported because new pools should be +// added here to be shared where required. +func newBufioReaderPoolWithSize(size int) *BufioReaderPool { + return &BufioReaderPool{ + pool: sync.Pool{ + New: func() interface{} { return bufio.NewReaderSize(nil, size) }, + }, + } +} + +// Get returns a bufio.Reader which reads from r. The buffer size is that of the pool. +func (bufPool *BufioReaderPool) Get(r io.Reader) *bufio.Reader { + buf := bufPool.pool.Get().(*bufio.Reader) + buf.Reset(r) + return buf +} + +// Put puts the bufio.Reader back into the pool. +func (bufPool *BufioReaderPool) Put(b *bufio.Reader) { + b.Reset(nil) + bufPool.pool.Put(b) +} + +type bufferPool struct { + pool sync.Pool +} + +func newBufferPoolWithSize(size int) *bufferPool { + return &bufferPool{ + pool: sync.Pool{ + New: func() interface{} { s := make([]byte, size); return &s }, + }, + } +} + +func (bp *bufferPool) Get() *[]byte { + return bp.pool.Get().(*[]byte) +} + +func (bp *bufferPool) Put(b *[]byte) { + bp.pool.Put(b) +} + +// Copy is a convenience wrapper which uses a buffer to avoid allocation in io.Copy. +func Copy(dst io.Writer, src io.Reader) (written int64, err error) { + buf := buffer32KPool.Get() + written, err = io.CopyBuffer(dst, src, *buf) + buffer32KPool.Put(buf) + return +} + +// NewReadCloserWrapper returns a wrapper which puts the bufio.Reader back +// into the pool and closes the reader if it's an io.ReadCloser. +func (bufPool *BufioReaderPool) NewReadCloserWrapper(buf *bufio.Reader, r io.Reader) io.ReadCloser { + return ioutils.NewReadCloserWrapper(r, func() error { + if readCloser, ok := r.(io.ReadCloser); ok { + readCloser.Close() + } + bufPool.Put(buf) + return nil + }) +} + +// BufioWriterPool is a bufio writer that uses sync.Pool. +type BufioWriterPool struct { + pool sync.Pool +} + +// newBufioWriterPoolWithSize is unexported because new pools should be +// added here to be shared where required. +func newBufioWriterPoolWithSize(size int) *BufioWriterPool { + return &BufioWriterPool{ + pool: sync.Pool{ + New: func() interface{} { return bufio.NewWriterSize(nil, size) }, + }, + } +} + +// Get returns a bufio.Writer which writes to w. The buffer size is that of the pool. +func (bufPool *BufioWriterPool) Get(w io.Writer) *bufio.Writer { + buf := bufPool.pool.Get().(*bufio.Writer) + buf.Reset(w) + return buf +} + +// Put puts the bufio.Writer back into the pool. +func (bufPool *BufioWriterPool) Put(b *bufio.Writer) { + b.Reset(nil) + bufPool.pool.Put(b) +} + +// NewWriteCloserWrapper returns a wrapper which puts the bufio.Writer back +// 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() + if writeCloser, ok := w.(io.WriteCloser); ok { + writeCloser.Close() + } + bufPool.Put(buf) + return nil + }) +} diff --git a/vendor/github.com/docker/docker/pkg/stringid/stringid.go b/vendor/github.com/docker/docker/pkg/stringid/stringid.go index a79c9672..bffac803 100644 --- a/vendor/github.com/docker/docker/pkg/stringid/stringid.go +++ b/vendor/github.com/docker/docker/pkg/stringid/stringid.go @@ -4,6 +4,9 @@ package stringid // import "github.com/docker/docker/pkg/stringid" import ( "crypto/rand" "encoding/hex" + "errors" + "regexp" + "strconv" "strings" ) @@ -12,6 +15,22 @@ const ( fullLen = 64 ) +var ( + validShortID = regexp.MustCompile("^[a-f0-9]{12}$") + validHex = regexp.MustCompile(`^[a-f0-9]{64}$`) +) + +// IsShortID determines if id has the correct format and length for a short ID. +// It checks the IDs length and if it consists of valid characters for IDs (a-f0-9). +// +// Deprecated: this function is no longer used, and will be removed in the next release. +func IsShortID(id string) bool { + if len(id) != shortLen { + return false + } + return validShortID.MatchString(id) +} + // TruncateID returns a shorthand version of a string identifier for convenience. // A collision with other shorthands is very unlikely, but possible. // In case of a collision a lookup with TruncIndex.Get() will fail, and the caller @@ -26,10 +45,7 @@ func TruncateID(id string) string { return id } -// GenerateRandomID returns a unique, 64-character ID consisting of a-z, 0-9. -// It guarantees that the ID, when truncated ([TruncateID]) does not consist -// of numbers only, so that the truncated ID can be used as hostname for -// containers. +// GenerateRandomID returns a unique id. func GenerateRandomID() string { b := make([]byte, 32) for { @@ -37,27 +53,25 @@ func GenerateRandomID() string { panic(err) // This shouldn't happen } id := hex.EncodeToString(b) - - // make sure that the truncated ID does not consist of only numeric - // characters, as it's used as default hostname for containers. - // - // See: - // - https://github.com/moby/moby/issues/3869 - // - https://bugzilla.redhat.com/show_bug.cgi?id=1059122 - if allNum(id[:shortLen]) { - // all numbers; try again + // if we try to parse the truncated for as an int and we don't have + // an error then the value is all numeric and causes issues when + // used as a hostname. ref #3869 + if _, err := strconv.ParseInt(TruncateID(id), 10, 64); err == nil { continue } return id } } -// allNum checks whether id consists of only numbers (0-9). -func allNum(id string) bool { - for _, c := range []byte(id) { - if c > '9' || c < '0' { - return false - } +// ValidateID checks whether an ID string is a valid, full-length image ID. +// +// Deprecated: use [github.com/docker/docker/image/v1.ValidateID] instead. Will be removed in the next release. +func ValidateID(id string) error { + if len(id) != fullLen { + return errors.New("image ID '" + id + "' is invalid") } - return true + if !validHex.MatchString(id) { + return errors.New("image ID '" + id + "' is invalid") + } + return nil } diff --git a/vendor/github.com/docker/docker/pkg/system/args_windows.go b/vendor/github.com/docker/docker/pkg/system/args_windows.go new file mode 100644 index 00000000..b7c9487a --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/args_windows.go @@ -0,0 +1,16 @@ +package system // import "github.com/docker/docker/pkg/system" + +import ( + "strings" + + "golang.org/x/sys/windows" +) + +// EscapeArgs makes a Windows-style escaped command line from a set of arguments +func EscapeArgs(args []string) string { + escapedArgs := make([]string, len(args)) + for i, a := range args { + escapedArgs[i] = windows.EscapeArg(a) + } + return strings.Join(escapedArgs, " ") +} diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes.go b/vendor/github.com/docker/docker/pkg/system/chtimes.go new file mode 100644 index 00000000..6a6bca43 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/chtimes.go @@ -0,0 +1,48 @@ +package system // import "github.com/docker/docker/pkg/system" + +import ( + "os" + "syscall" + "time" + "unsafe" +) + +// Used by Chtimes +var unixEpochTime, unixMaxTime time.Time + +func init() { + unixEpochTime = time.Unix(0, 0) + if unsafe.Sizeof(syscall.Timespec{}.Nsec) == 8 { + // This is a 64 bit timespec + // os.Chtimes limits time to the following + // + // Note that this intentionally sets nsec (not sec), which sets both sec + // and nsec internally in time.Unix(); + // https://github.com/golang/go/blob/go1.19.2/src/time/time.go#L1364-L1380 + unixMaxTime = time.Unix(0, 1<<63-1) + } else { + // This is a 32 bit timespec + unixMaxTime = time.Unix(1<<31-1, 0) + } +} + +// Chtimes changes the access time and modified time of a file at the given path. +// If the modified time is prior to the Unix Epoch (unixMinTime), or after the +// end of Unix Time (unixEpochTime), os.Chtimes has undefined behavior. In this +// case, Chtimes defaults to Unix Epoch, just in case. +func Chtimes(name string, atime time.Time, mtime time.Time) error { + if atime.Before(unixEpochTime) || atime.After(unixMaxTime) { + atime = unixEpochTime + } + + if mtime.Before(unixEpochTime) || mtime.After(unixMaxTime) { + mtime = unixEpochTime + } + + if err := os.Chtimes(name, atime, mtime); err != nil { + return err + } + + // Take platform specific action for setting create time. + return setCTime(name, mtime) +} diff --git a/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go new file mode 100644 index 00000000..92ff0209 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/chtimes_nowindows.go @@ -0,0 +1,14 @@ +//go:build !windows + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "time" +) + +// setCTime will set the create time on a file. On Unix, the create +// time is updated as a side effect of setting the modified time, so +// no action is required. +func setCTime(path string, ctime time.Time) error { + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/archive/time_windows.go b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go similarity index 50% rename from vendor/github.com/docker/docker/pkg/archive/time_windows.go rename to vendor/github.com/docker/docker/pkg/system/chtimes_windows.go index af1f7c8f..ab478f5c 100644 --- a/vendor/github.com/docker/docker/pkg/archive/time_windows.go +++ b/vendor/github.com/docker/docker/pkg/system/chtimes_windows.go @@ -1,18 +1,15 @@ -package archive +package system // import "github.com/docker/docker/pkg/system" import ( - "os" "time" "golang.org/x/sys/windows" ) -func chtimes(name string, atime time.Time, mtime time.Time) error { - if err := os.Chtimes(name, atime, mtime); err != nil { - return err - } - - pathp, err := windows.UTF16PtrFromString(name) +// setCTime will set the create time on a file. On Windows, this requires +// calling SetFileTime and explicitly including the create time. +func setCTime(path string, ctime time.Time) error { + pathp, err := windows.UTF16PtrFromString(path) if err != nil { return err } @@ -23,10 +20,6 @@ func chtimes(name string, atime time.Time, mtime time.Time) error { return err } defer windows.Close(h) - c := windows.NsecToFiletime(mtime.UnixNano()) + c := windows.NsecToFiletime(ctime.UnixNano()) return windows.SetFileTime(h, &c, nil, nil) } - -func lchtimes(name string, atime time.Time, mtime time.Time) error { - return nil -} diff --git a/vendor/github.com/docker/docker/pkg/system/errors.go b/vendor/github.com/docker/docker/pkg/system/errors.go new file mode 100644 index 00000000..f4bbcce7 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/errors.go @@ -0,0 +1,6 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "errors" + +// ErrNotSupportedPlatform means the platform is not supported. +var ErrNotSupportedPlatform = errors.New("platform and architecture is not supported") diff --git a/vendor/github.com/docker/docker/pkg/system/filesys.go b/vendor/github.com/docker/docker/pkg/system/filesys.go new file mode 100644 index 00000000..ce5990c9 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/filesys.go @@ -0,0 +1,19 @@ +package system + +import ( + "os" + "path/filepath" + "strings" +) + +// IsAbs is a platform-agnostic wrapper for filepath.IsAbs. +// +// On Windows, golang filepath.IsAbs does not consider a path \windows\system32 +// as absolute as it doesn't start with a drive-letter/colon combination. However, +// in docker we need to verify things such as WORKDIR /windows/system32 in +// a Dockerfile (which gets translated to \windows\system32 when being processed +// by the daemon). This SHOULD be treated as absolute from a docker processing +// perspective. +func IsAbs(path string) bool { + return filepath.IsAbs(path) || strings.HasPrefix(path, string(os.PathSeparator)) +} diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_unix.go b/vendor/github.com/docker/docker/pkg/system/filesys_unix.go new file mode 100644 index 00000000..f01f9385 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/filesys_unix.go @@ -0,0 +1,16 @@ +//go:build !windows + +package system // import "github.com/docker/docker/pkg/system" + +import "os" + +// MkdirAllWithACL is a wrapper for os.MkdirAll on unix systems. +func MkdirAllWithACL(path string, perm os.FileMode, sddl string) error { + return os.MkdirAll(path, perm) +} + +// MkdirAll creates a directory named path along with any necessary parents, +// with permission specified by attribute perm for all dir created. +func MkdirAll(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} diff --git a/vendor/github.com/docker/docker/pkg/system/filesys_windows.go b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go new file mode 100644 index 00000000..92e972ea --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/filesys_windows.go @@ -0,0 +1,135 @@ +package system // import "github.com/docker/docker/pkg/system" + +import ( + "os" + "regexp" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System. +const SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)" + +// volumePath is a regular expression to check if a path is a Windows +// volume path (e.g., "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}" +// or "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\"). +var volumePath = regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}\\?$`) + +// MkdirAllWithACL is a custom version of os.MkdirAll modified for use on Windows +// so that it is both volume path aware, and can create a directory with +// an appropriate SDDL defined ACL. +func MkdirAllWithACL(path string, _ os.FileMode, sddl string) error { + sa, err := makeSecurityAttributes(sddl) + if err != nil { + return &os.PathError{Op: "mkdirall", Path: path, Err: err} + } + return mkdirall(path, sa) +} + +// MkdirAll is a custom version of os.MkdirAll that is volume path aware for +// Windows. It can be used as a drop-in replacement for os.MkdirAll. +func MkdirAll(path string, _ os.FileMode) error { + return mkdirall(path, nil) +} + +// mkdirall is a custom version of os.MkdirAll modified for use on Windows +// so that it is both volume path aware, and can create a directory with +// a DACL. +func mkdirall(path string, perm *windows.SecurityAttributes) error { + if volumePath.MatchString(path) { + return nil + } + + // The rest of this method is largely copied from os.MkdirAll and should be kept + // as-is to ensure compatibility. + + // Fast path: if we can tell whether path is a directory or file, stop with success or error. + dir, err := os.Stat(path) + if err == nil { + if dir.IsDir() { + return nil + } + return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} + } + + // Slow path: make sure parent exists and then call Mkdir for path. + i := len(path) + for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. + i-- + } + + j := i + for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. + j-- + } + + if j > 1 { + // Create parent. + err = mkdirall(fixRootDirectory(path[:j-1]), perm) + if err != nil { + return err + } + } + + // Parent now exists; invoke Mkdir and use its result. + err = mkdirWithACL(path, perm) + if err != nil { + // Handle arguments like "foo/." by + // double-checking that directory doesn't exist. + dir, err1 := os.Lstat(path) + if err1 == nil && dir.IsDir() { + return nil + } + return err + } + return nil +} + +// mkdirWithACL creates a new directory. If there is an error, it will be of +// type *PathError. . +// +// This is a modified and combined version of os.Mkdir and windows.Mkdir +// in golang to cater for creating a directory am ACL permitting full +// access, with inheritance, to any subfolder/file for Built-in Administrators +// and Local System. +func mkdirWithACL(name string, sa *windows.SecurityAttributes) error { + if sa == nil { + return os.Mkdir(name, 0) + } + + namep, err := windows.UTF16PtrFromString(name) + if err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + + err = windows.CreateDirectory(namep, sa) + if err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return nil +} + +// fixRootDirectory fixes a reference to a drive's root directory to +// have the required trailing slash. +func fixRootDirectory(p string) string { + if len(p) == len(`\\?\c:`) { + if os.IsPathSeparator(p[0]) && os.IsPathSeparator(p[1]) && p[2] == '?' && os.IsPathSeparator(p[3]) && p[5] == ':' { + return p + `\` + } + } + return p +} + +func makeSecurityAttributes(sddl string) (*windows.SecurityAttributes, error) { + var sa windows.SecurityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + sa.InheritHandle = 1 + var err error + sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString(sddl) + if err != nil { + return nil, err + } + return &sa, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/init_windows.go b/vendor/github.com/docker/docker/pkg/system/init_windows.go new file mode 100644 index 00000000..7603efbb --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/init_windows.go @@ -0,0 +1,16 @@ +package system // import "github.com/docker/docker/pkg/system" + +// containerdRuntimeSupported determines if containerd should be the runtime. +var containerdRuntimeSupported = false + +// InitContainerdRuntime sets whether to use containerd for runtime on Windows. +func InitContainerdRuntime(cdPath string) { + if len(cdPath) > 0 { + containerdRuntimeSupported = true + } +} + +// ContainerdRuntimeSupported returns true if the use of containerd runtime is supported. +func ContainerdRuntimeSupported() bool { + return containerdRuntimeSupported +} diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_unix.go b/vendor/github.com/docker/docker/pkg/system/lstat_unix.go new file mode 100644 index 00000000..97f355d2 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/lstat_unix.go @@ -0,0 +1,22 @@ +//go:build !windows + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "os" + "syscall" +) + +// Lstat takes a path to a file and returns +// a system.StatT type pertaining to that file. +// +// Throws an error if the file does not exist. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Lstat(path string) (*StatT, error) { + s := &syscall.Stat_t{} + if err := syscall.Lstat(path, s); err != nil { + return nil, &os.PathError{Op: "Lstat", Path: path, Err: err} + } + return fromStatT(s) +} diff --git a/vendor/github.com/docker/docker/pkg/system/lstat_windows.go b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go new file mode 100644 index 00000000..4180f3ac --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/lstat_windows.go @@ -0,0 +1,16 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "os" + +// Lstat calls os.Lstat to get a fileinfo interface back. +// This is then copied into our own locally defined structure. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Lstat(path string) (*StatT, error) { + fi, err := os.Lstat(path) + if err != nil { + return nil, err + } + + return fromStatT(&fi) +} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod.go b/vendor/github.com/docker/docker/pkg/system/mknod.go new file mode 100644 index 00000000..e0cd22d7 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/mknod.go @@ -0,0 +1,18 @@ +//go:build !windows + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "golang.org/x/sys/unix" +) + +// Mkdev is used to build the value of linux devices (in /dev/) which specifies major +// and minor number of the newly created device special file. +// Linux device nodes are a bit weird due to backwards compat with 16 bit device nodes. +// They are, from low to high: the lower 8 bits of the minor, then 12 bits of the major, +// then the top 12 bits of the minor. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Mkdev(major int64, minor int64) uint32 { + return uint32(unix.Mkdev(uint32(major), uint32(minor))) +} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go b/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go new file mode 100644 index 00000000..4f66453d --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/mknod_freebsd.go @@ -0,0 +1,15 @@ +//go:build freebsd + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "golang.org/x/sys/unix" +) + +// Mknod creates a filesystem node (file, device special file or named pipe) named path +// with attributes specified by mode and dev. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Mknod(path string, mode uint32, dev int) error { + return unix.Mknod(path, mode, uint64(dev)) +} diff --git a/vendor/github.com/docker/docker/pkg/system/mknod_unix.go b/vendor/github.com/docker/docker/pkg/system/mknod_unix.go new file mode 100644 index 00000000..34c55326 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/mknod_unix.go @@ -0,0 +1,15 @@ +//go:build !freebsd && !windows + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "golang.org/x/sys/unix" +) + +// Mknod creates a filesystem node (file, device special file or named pipe) named path +// with attributes specified by mode and dev. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Mknod(path string, mode uint32, dev int) error { + return unix.Mknod(path, mode, dev) +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_bsd.go b/vendor/github.com/docker/docker/pkg/system/stat_bsd.go new file mode 100644 index 00000000..435b776e --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_bsd.go @@ -0,0 +1,17 @@ +//go:build freebsd || netbsd + +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: uint32(s.Mode), + uid: s.Uid, + gid: s.Gid, + rdev: uint64(s.Rdev), + mtim: s.Mtimespec, + }, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_darwin.go b/vendor/github.com/docker/docker/pkg/system/stat_darwin.go new file mode 100644 index 00000000..e0b629df --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_darwin.go @@ -0,0 +1,15 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: uint32(s.Mode), + uid: s.Uid, + gid: s.Gid, + rdev: uint64(s.Rdev), + mtim: s.Mtimespec, + }, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_illumos.go b/vendor/github.com/docker/docker/pkg/system/stat_illumos.go new file mode 100644 index 00000000..851374e5 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_illumos.go @@ -0,0 +1,15 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: uint32(s.Mode), + uid: s.Uid, + gid: s.Gid, + rdev: uint64(s.Rdev), + mtim: s.Mtim, + }, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_linux.go b/vendor/github.com/docker/docker/pkg/system/stat_linux.go new file mode 100644 index 00000000..0557235f --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_linux.go @@ -0,0 +1,24 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: s.Mode, + uid: s.Uid, + gid: s.Gid, + // the type is 32bit on mips + rdev: uint64(s.Rdev), //nolint: unconvert + mtim: s.Mtim, + }, nil +} + +// FromStatT converts a syscall.Stat_t type to a system.Stat_t type +// This is exposed on Linux as pkg/archive/changes uses it. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func FromStatT(s *syscall.Stat_t) (*StatT, error) { + return fromStatT(s) +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go new file mode 100644 index 00000000..851374e5 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_openbsd.go @@ -0,0 +1,15 @@ +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// fromStatT converts a syscall.Stat_t type to a system.Stat_t type +func fromStatT(s *syscall.Stat_t) (*StatT, error) { + return &StatT{ + size: s.Size, + mode: uint32(s.Mode), + uid: s.Uid, + gid: s.Gid, + rdev: uint64(s.Rdev), + mtim: s.Mtim, + }, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_unix.go b/vendor/github.com/docker/docker/pkg/system/stat_unix.go new file mode 100644 index 00000000..661b0bed --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_unix.go @@ -0,0 +1,70 @@ +//go:build !windows + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "os" + "syscall" +) + +// StatT type contains status of a file. It contains metadata +// like permission, owner, group, size, etc about a file. +// +// Deprecated: this type is only used internally, and will be removed in the next release. +type StatT struct { + mode uint32 + uid uint32 + gid uint32 + rdev uint64 + size int64 + mtim syscall.Timespec +} + +// Mode returns file's permission mode. +func (s StatT) Mode() uint32 { + return s.mode +} + +// UID returns file's user id of owner. +func (s StatT) UID() uint32 { + return s.uid +} + +// GID returns file's group id of owner. +func (s StatT) GID() uint32 { + return s.gid +} + +// Rdev returns file's device ID (if it's special file). +func (s StatT) Rdev() uint64 { + return s.rdev +} + +// Size returns file's size. +func (s StatT) Size() int64 { + return s.size +} + +// Mtim returns file's last modification time. +func (s StatT) Mtim() syscall.Timespec { + return s.mtim +} + +// IsDir reports whether s describes a directory. +func (s StatT) IsDir() bool { + return s.mode&syscall.S_IFDIR != 0 +} + +// Stat takes a path to a file and returns +// a system.StatT type pertaining to that file. +// +// Throws an error if the file does not exist. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Stat(path string) (*StatT, error) { + s := &syscall.Stat_t{} + if err := syscall.Stat(path, s); err != nil { + return nil, &os.PathError{Op: "Stat", Path: path, Err: err} + } + return fromStatT(s) +} diff --git a/vendor/github.com/docker/docker/pkg/system/stat_windows.go b/vendor/github.com/docker/docker/pkg/system/stat_windows.go new file mode 100644 index 00000000..e74a0f4f --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/stat_windows.go @@ -0,0 +1,54 @@ +package system // import "github.com/docker/docker/pkg/system" + +import ( + "os" + "time" +) + +// StatT type contains status of a file. It contains metadata +// like permission, size, etc about a file. +// +// Deprecated: this type is only used internally, and will be removed in the next release. +type StatT struct { + mode os.FileMode + size int64 + mtim time.Time +} + +// Size returns file's size. +func (s StatT) Size() int64 { + return s.size +} + +// Mode returns file's permission mode. +func (s StatT) Mode() os.FileMode { + return s.mode +} + +// Mtim returns file's last modification time. +func (s StatT) Mtim() time.Time { + return s.mtim +} + +// Stat takes a path to a file and returns +// a system.StatT type pertaining to that file. +// +// Throws an error if the file does not exist. +// +// Deprecated: this function is only used internally, and will be removed in the next release. +func Stat(path string) (*StatT, error) { + fi, err := os.Stat(path) + if err != nil { + return nil, err + } + return fromStatT(&fi) +} + +// fromStatT converts a os.FileInfo type to a system.StatT type +func fromStatT(fi *os.FileInfo) (*StatT, error) { + return &StatT{ + size: (*fi).Size(), + mode: (*fi).Mode(), + mtim: (*fi).ModTime(), + }, nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unix.go b/vendor/github.com/docker/docker/pkg/system/utimes_unix.go new file mode 100644 index 00000000..f3a079f8 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/utimes_unix.go @@ -0,0 +1,24 @@ +//go:build linux || freebsd + +package system // import "github.com/docker/docker/pkg/system" + +import ( + "syscall" + + "golang.org/x/sys/unix" +) + +// LUtimesNano is used to change access and modification time of the specified path. +// It's used for symbol link file because unix.UtimesNano doesn't support a NOFOLLOW flag atm. +func LUtimesNano(path string, ts []syscall.Timespec) error { + uts := []unix.Timespec{ + unix.NsecToTimespec(syscall.TimespecToNsec(ts[0])), + unix.NsecToTimespec(syscall.TimespecToNsec(ts[1])), + } + err := unix.UtimesNanoAt(unix.AT_FDCWD, path, uts, unix.AT_SYMLINK_NOFOLLOW) + if err != nil && err != unix.ENOSYS { + return err + } + + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go new file mode 100644 index 00000000..7c19d591 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/utimes_unsupported.go @@ -0,0 +1,10 @@ +//go:build !linux && !freebsd + +package system // import "github.com/docker/docker/pkg/system" + +import "syscall" + +// LUtimesNano is only supported on linux and freebsd. +func LUtimesNano(path string, ts []syscall.Timespec) error { + return ErrNotSupportedPlatform +} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs.go b/vendor/github.com/docker/docker/pkg/system/xattrs.go new file mode 100644 index 00000000..b3f4e8a2 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/xattrs.go @@ -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() +} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go new file mode 100644 index 00000000..b877ecc5 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/xattrs_linux.go @@ -0,0 +1,47 @@ +package system // import "github.com/docker/docker/pkg/system" + +import ( + "golang.org/x/sys/unix" +) + +// Lgetxattr retrieves the value of the extended attribute identified by attr +// and associated with the given path in the file system. +// 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} + } + + // Start with a 128 length byte array + dest := make([]byte, 128) + sz, errno := unix.Lgetxattr(path, attr, dest) + + for errno == unix.ERANGE { + // Buffer too small, use zero-sized buffer to get the actual size + sz, errno = unix.Lgetxattr(path, attr, []byte{}) + if errno != nil { + return sysErr(errno) + } + dest = make([]byte, sz) + sz, errno = unix.Lgetxattr(path, attr, dest) + } + + switch { + case errno == unix.ENODATA: + return nil, nil + case errno != nil: + return sysErr(errno) + } + + return dest[:sz], nil +} + +// Lsetxattr sets the value of the extended attribute identified by attr +// and associated with the given path in the file system. +func Lsetxattr(path string, attr string, data []byte, flags int) error { + err := unix.Lsetxattr(path, attr, data, flags) + if err != nil { + return &XattrError{Op: "lsetxattr", Attr: attr, Path: path, Err: err} + } + return nil +} diff --git a/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go new file mode 100644 index 00000000..2a3698f1 --- /dev/null +++ b/vendor/github.com/docker/docker/pkg/system/xattrs_unsupported.go @@ -0,0 +1,13 @@ +//go:build !linux + +package system // import "github.com/docker/docker/pkg/system" + +// Lgetxattr is not supported on platforms other than linux. +func Lgetxattr(path string, attr string) ([]byte, error) { + return nil, ErrNotSupportedPlatform +} + +// Lsetxattr is not supported on platforms other than linux. +func Lsetxattr(path string, attr string, data []byte, flags int) error { + return ErrNotSupportedPlatform +} diff --git a/vendor/github.com/docker/docker/registry/auth.go b/vendor/github.com/docker/docker/registry/auth.go index 8c62b83c..905ccf5f 100644 --- a/vendor/github.com/docker/docker/registry/auth.go +++ b/vendor/github.com/docker/docker/registry/auth.go @@ -66,23 +66,23 @@ func (scs staticCredentialStore) SetRefreshToken(*url.URL, string, string) { // loginV2 tries to login to the v2 registry server. The given registry // endpoint will be pinged to get authorization challenges. These challenges // will be used to authenticate against the registry to validate credentials. -func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (status string, token string, _ error) { - endpointStr := strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" - log.G(context.TODO()).Debugf("attempting v2 login to registry endpoint %s", endpointStr) - - req, err := http.NewRequest(http.MethodGet, endpointStr, nil) - if err != nil { - return "", "", err - } - +func loginV2(authConfig *registry.AuthConfig, endpoint APIEndpoint, userAgent string) (string, string, error) { var ( + endpointStr = strings.TrimRight(endpoint.URL.String(), "/") + "/v2/" modifiers = Headers(userAgent, nil) - authTrans = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) + authTransport = transport.NewTransport(newTransport(endpoint.TLSConfig), modifiers...) credentialAuthConfig = *authConfig creds = loginCredentialStore{authConfig: &credentialAuthConfig} ) - loginClient, err := v2AuthHTTPClient(endpoint.URL, authTrans, modifiers, creds, nil) + log.G(context.TODO()).Debugf("attempting v2 login to registry endpoint %s", endpointStr) + + loginClient, err := v2AuthHTTPClient(endpoint.URL, authTransport, modifiers, creds, nil) + if err != nil { + return "", "", err + } + + req, err := http.NewRequest(http.MethodGet, endpointStr, nil) if err != nil { return "", "", err } @@ -133,13 +133,12 @@ func v2AuthHTTPClient(endpoint *url.URL, authTransport http.RoundTripper, modifi // files). func ConvertToHostname(url string) string { stripped := url - if strings.HasPrefix(stripped, "http://") { - stripped = strings.TrimPrefix(stripped, "http://") - } else if strings.HasPrefix(stripped, "https://") { - stripped = strings.TrimPrefix(stripped, "https://") + if strings.HasPrefix(url, "http://") { + stripped = strings.TrimPrefix(url, "http://") + } else if strings.HasPrefix(url, "https://") { + stripped = strings.TrimPrefix(url, "https://") } - stripped, _, _ = strings.Cut(stripped, "/") - return stripped + return strings.SplitN(stripped, "/", 2)[0] } // ResolveAuthConfig matches an auth configuration to a server address or a URL diff --git a/vendor/github.com/docker/docker/registry/config.go b/vendor/github.com/docker/docker/registry/config.go index f8d94ce8..e1b0a0ca 100644 --- a/vendor/github.com/docker/docker/registry/config.go +++ b/vendor/github.com/docker/docker/registry/config.go @@ -4,21 +4,20 @@ import ( "context" "net" "net/url" + "regexp" "strconv" "strings" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/docker/api/types/registry" - "github.com/docker/docker/internal/lazyregexp" ) // ServiceOptions holds command line options. type ServiceOptions struct { - AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. - - Mirrors []string `json:"registry-mirrors,omitempty"` - InsecureRegistries []string `json:"insecure-registries,omitempty"` + AllowNondistributableArtifacts []string `json:"allow-nondistributable-artifacts,omitempty"` + Mirrors []string `json:"registry-mirrors,omitempty"` + InsecureRegistries []string `json:"insecure-registries,omitempty"` } // serviceConfig holds daemon configuration for the registry service. @@ -57,7 +56,10 @@ var ( } emptyServiceConfig, _ = newServiceConfig(ServiceOptions{}) - validHostPortRegex = lazyregexp.New(`^` + reference.DomainRegexp.String() + `$`) + validHostPortRegex = regexp.MustCompile(`^` + reference.DomainRegexp.String() + `$`) + + // for mocking in unit tests + lookupIP = net.LookupIP // certsDir is used to override defaultCertsDir. certsDir string @@ -81,6 +83,9 @@ func CertsDir() string { // newServiceConfig returns a new instance of ServiceConfig func newServiceConfig(options ServiceOptions) (*serviceConfig, error) { config := &serviceConfig{} + if err := config.loadAllowNondistributableArtifacts(options.AllowNondistributableArtifacts); err != nil { + return nil, err + } if err := config.loadMirrors(options.Mirrors); err != nil { return nil, err } @@ -98,12 +103,51 @@ func (config *serviceConfig) copy() *registry.ServiceConfig { ic[key] = value } return ®istry.ServiceConfig{ - InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), - IndexConfigs: ic, - Mirrors: append([]string(nil), config.Mirrors...), + AllowNondistributableArtifactsCIDRs: append([]*registry.NetIPNet(nil), config.AllowNondistributableArtifactsCIDRs...), + AllowNondistributableArtifactsHostnames: append([]string(nil), config.AllowNondistributableArtifactsHostnames...), + InsecureRegistryCIDRs: append([]*registry.NetIPNet(nil), config.InsecureRegistryCIDRs...), + IndexConfigs: ic, + Mirrors: append([]string(nil), config.Mirrors...), } } +// loadAllowNondistributableArtifacts loads allow-nondistributable-artifacts registries into config. +func (config *serviceConfig) loadAllowNondistributableArtifacts(registries []string) error { + cidrs := map[string]*registry.NetIPNet{} + hostnames := map[string]bool{} + + for _, r := range registries { + if _, err := ValidateIndexName(r); err != nil { + return err + } + if hasScheme(r) { + return invalidParamf("allow-nondistributable-artifacts registry %s should not contain '://'", r) + } + + if _, ipnet, err := net.ParseCIDR(r); err == nil { + // Valid CIDR. + cidrs[ipnet.String()] = (*registry.NetIPNet)(ipnet) + } else if err = validateHostPort(r); err == nil { + // Must be `host:port` if not CIDR. + hostnames[r] = true + } else { + return invalidParamWrapf(err, "allow-nondistributable-artifacts registry %s is not valid", r) + } + } + + config.AllowNondistributableArtifactsCIDRs = make([]*registry.NetIPNet, 0, len(cidrs)) + for _, c := range cidrs { + config.AllowNondistributableArtifactsCIDRs = append(config.AllowNondistributableArtifactsCIDRs, c) + } + + config.AllowNondistributableArtifactsHostnames = make([]string, 0, len(hostnames)) + for h := range hostnames { + config.AllowNondistributableArtifactsHostnames = append(config.AllowNondistributableArtifactsHostnames, h) + } + + return nil +} + // loadMirrors loads mirrors to config, after removing duplicates. // Returns an error if mirrors contains an invalid mirror. func (config *serviceConfig) loadMirrors(mirrors []string) error { @@ -140,7 +184,7 @@ func (config *serviceConfig) loadMirrors(mirrors []string) error { func (config *serviceConfig) loadInsecureRegistries(registries []string) error { // Localhost is by default considered as an insecure registry. This is a // stop-gap for people who are running a private registry on localhost. - registries = append(registries, "::1/128", "127.0.0.0/8") + registries = append(registries, "127.0.0.0/8") var ( insecureRegistryCIDRs = make([]*registry.NetIPNet, 0) @@ -201,6 +245,25 @@ skip: return nil } +// allowNondistributableArtifacts returns true if the provided hostname is part of the list of registries +// that allow push of nondistributable artifacts. +// +// The list can contain elements with CIDR notation to specify a whole subnet. If the subnet contains an IP +// of the registry specified by hostname, true is returned. +// +// hostname should be a URL.Host (`host:port` or `host`) where the `host` part can be either a domain name +// or an IP address. If it is a domain name, then it will be resolved to IP addresses for matching. If +// resolution fails, CIDR matching is not performed. +func (config *serviceConfig) allowNondistributableArtifacts(hostname string) bool { + for _, h := range config.AllowNondistributableArtifactsHostnames { + if h == hostname { + return true + } + } + + return isCIDRMatch(config.AllowNondistributableArtifactsCIDRs, hostname) +} + // isSecureIndex returns false if the provided indexName is part of the list of insecure registries // Insecure registries accept HTTP and/or accept HTTPS with certificates from unknown CAs. // @@ -222,37 +285,30 @@ func (config *serviceConfig) isSecureIndex(indexName string) bool { return !isCIDRMatch(config.InsecureRegistryCIDRs, indexName) } -// for mocking in unit tests. -var lookupIP = net.LookupIP - // isCIDRMatch returns true if URLHost matches an element of cidrs. URLHost is a URL.Host (`host:port` or `host`) // where the `host` part can be either a domain name or an IP address. If it is a domain name, then it will be // resolved to IP addresses for matching. If resolution fails, false is returned. func isCIDRMatch(cidrs []*registry.NetIPNet, URLHost string) bool { - if len(cidrs) == 0 { - return false - } - host, _, err := net.SplitHostPort(URLHost) if err != nil { - // Assume URLHost is a host without port and go on. + // Assume URLHost is of the form `host` without the port and go on. host = URLHost } - var addresses []net.IP - if ip := net.ParseIP(host); ip != nil { - // Host is an IP-address. - addresses = append(addresses, ip) - } else { - // Try to resolve the host's IP-address. - addresses, err = lookupIP(host) - if err != nil { - // We failed to resolve the host; assume there's no match. - return false + addrs, err := lookupIP(host) + if err != nil { + ip := net.ParseIP(host) + if ip != nil { + addrs = []net.IP{ip} } + + // if ip == nil, then `host` is neither an IP nor it could be looked up, + // either because the index is unreachable, or because the index is behind an HTTP proxy. + // So, len(addrs) == 0 and we're not aborting. } - for _, addr := range addresses { + // Try CIDR notation only if addrs has any elements, i.e. if `host`'s IP could be determined. + for _, addr := range addrs { for _, ipnet := range cidrs { // check if the addr falls in the subnet if (*net.IPNet)(ipnet).Contains(addr) { diff --git a/vendor/github.com/docker/docker/registry/registry.go b/vendor/github.com/docker/docker/registry/registry.go index 6b079199..7866dcd0 100644 --- a/vendor/github.com/docker/docker/registry/registry.go +++ b/vendor/github.com/docker/docker/registry/registry.go @@ -14,7 +14,6 @@ import ( "github.com/containerd/log" "github.com/docker/distribution/registry/client/transport" "github.com/docker/go-connections/tlsconfig" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) // HostCertsDir returns the config directory for a specific host. @@ -116,7 +115,7 @@ func Headers(userAgent string, metaHeaders http.Header) []transport.RequestModif // newTransport returns a new HTTP transport. If tlsConfig is nil, it uses the // default TLS configuration. -func newTransport(tlsConfig *tls.Config) http.RoundTripper { +func newTransport(tlsConfig *tls.Config) *http.Transport { if tlsConfig == nil { tlsConfig = tlsconfig.ServerDefault() } @@ -126,14 +125,12 @@ func newTransport(tlsConfig *tls.Config) http.RoundTripper { KeepAlive: 30 * time.Second, } - return otelhttp.NewTransport( - &http.Transport{ - Proxy: http.ProxyFromEnvironment, - DialContext: direct.DialContext, - TLSHandshakeTimeout: 10 * time.Second, - TLSClientConfig: tlsConfig, - // TODO(dmcgowan): Call close idle connections when complete and use keep alive - DisableKeepAlives: true, - }, - ) + return &http.Transport{ + Proxy: http.ProxyFromEnvironment, + DialContext: direct.DialContext, + TLSHandshakeTimeout: 10 * time.Second, + TLSClientConfig: tlsConfig, + // TODO(dmcgowan): Call close idle connections when complete and use keep alive + DisableKeepAlives: true, + } } diff --git a/vendor/github.com/docker/docker/registry/search_session.go b/vendor/github.com/docker/docker/registry/search_session.go index a0d25c80..c334143c 100644 --- a/vendor/github.com/docker/docker/registry/search_session.go +++ b/vendor/github.com/docker/docker/registry/search_session.go @@ -6,7 +6,6 @@ import ( _ "crypto/sha512" "encoding/json" "fmt" - "io" "net/http" "net/http/cookiejar" "net/url" @@ -16,6 +15,7 @@ import ( "github.com/containerd/log" "github.com/docker/docker/api/types/registry" "github.com/docker/docker/errdefs" + "github.com/docker/docker/pkg/ioutils" "github.com/pkg/errors" ) @@ -76,35 +76,6 @@ func cloneRequest(r *http.Request) *http.Request { return r2 } -// onEOFReader wraps an io.ReadCloser and a function -// the function will run at the end of file or close the file. -type onEOFReader struct { - Rc io.ReadCloser - Fn func() -} - -func (r *onEOFReader) Read(p []byte) (n int, err error) { - n, err = r.Rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -// Close closes the file and run the function. -func (r *onEOFReader) Close() error { - err := r.Rc.Close() - r.runFunc() - return err -} - -func (r *onEOFReader) runFunc() { - if fn := r.Fn; fn != nil { - fn() - r.Fn = nil - } -} - // RoundTrip changes an HTTP request's headers to add the necessary // authentication-related headers func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { @@ -148,7 +119,7 @@ func (tr *authTransport) RoundTrip(orig *http.Request) (*http.Response, error) { if len(resp.Header["X-Docker-Token"]) > 0 { tr.token = resp.Header["X-Docker-Token"] } - resp.Body = &onEOFReader{ + resp.Body = &ioutils.OnEOFReader{ Rc: resp.Body, Fn: func() { tr.mu.Lock() diff --git a/vendor/github.com/docker/docker/registry/service.go b/vendor/github.com/docker/docker/registry/service.go index 4d66523c..6881c110 100644 --- a/vendor/github.com/docker/docker/registry/service.go +++ b/vendor/github.com/docker/docker/registry/service.go @@ -68,11 +68,10 @@ func (s *Service) Auth(ctx context.Context, authConfig *registry.AuthConfig, use registryHostName = u.Host } - // Lookup endpoints for authentication but exclude mirrors to prevent - // sending credentials of the upstream registry to a mirror. - s.mu.RLock() - endpoints, err := s.lookupV2Endpoints(registryHostName, false) - s.mu.RUnlock() + // Lookup endpoints for authentication using "LookupPushEndpoints", which + // excludes mirrors to prevent sending credentials of the upstream registry + // to a mirror. + endpoints, err := s.LookupPushEndpoints(registryHostName) if err != nil { return "", "", invalidParam(err) } @@ -104,9 +103,10 @@ func (s *Service) ResolveRepository(name reference.Named) (*RepositoryInfo, erro type APIEndpoint struct { Mirror bool URL *url.URL - AllowNondistributableArtifacts bool // Deprecated: non-distributable artifacts are deprecated and enabled by default. This field will be removed in the next release. + Version APIVersion // Deprecated: v1 registries are deprecated, and endpoints are always v2. + AllowNondistributableArtifacts bool Official bool - TrimHostname bool // Deprecated: hostname is now trimmed unconditionally for remote names. This field will be removed in the next release. + TrimHostname bool TLSConfig *tls.Config } @@ -116,7 +116,7 @@ func (s *Service) LookupPullEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - return s.lookupV2Endpoints(hostname, true) + return s.lookupV2Endpoints(hostname) } // LookupPushEndpoints creates a list of v2 endpoints to try to push to, in order of preference. @@ -125,7 +125,15 @@ func (s *Service) LookupPushEndpoints(hostname string) (endpoints []APIEndpoint, s.mu.RLock() defer s.mu.RUnlock() - return s.lookupV2Endpoints(hostname, false) + allEndpoints, err := s.lookupV2Endpoints(hostname) + if err == nil { + for _, endpoint := range allEndpoints { + if !endpoint.Mirror { + endpoints = append(endpoints, endpoint) + } + } + } + return endpoints, err } // IsInsecureRegistry returns true if the registry at given host is configured as diff --git a/vendor/github.com/docker/docker/registry/service_v2.go b/vendor/github.com/docker/docker/registry/service_v2.go index 43754527..5d09e11c 100644 --- a/vendor/github.com/docker/docker/registry/service_v2.go +++ b/vendor/github.com/docker/docker/registry/service_v2.go @@ -7,33 +7,38 @@ import ( "github.com/docker/go-connections/tlsconfig" ) -func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]APIEndpoint, error) { - var endpoints []APIEndpoint +func (s *Service) lookupV2Endpoints(hostname string) (endpoints []APIEndpoint, err error) { + ana := s.config.allowNondistributableArtifacts(hostname) + if hostname == DefaultNamespace || hostname == IndexHostname { - if includeMirrors { - for _, mirror := range s.config.Mirrors { - if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { - mirror = "https://" + mirror - } - mirrorURL, err := url.Parse(mirror) - if err != nil { - return nil, invalidParam(err) - } - mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) - if err != nil { - return nil, err - } - endpoints = append(endpoints, APIEndpoint{ - URL: mirrorURL, - Mirror: true, - TLSConfig: mirrorTLSConfig, - }) + for _, mirror := range s.config.Mirrors { + if !strings.HasPrefix(mirror, "http://") && !strings.HasPrefix(mirror, "https://") { + mirror = "https://" + mirror } + mirrorURL, err := url.Parse(mirror) + if err != nil { + return nil, invalidParam(err) + } + mirrorTLSConfig, err := newTLSConfig(mirrorURL.Host, s.config.isSecureIndex(mirrorURL.Host)) + if err != nil { + return nil, err + } + endpoints = append(endpoints, APIEndpoint{ + URL: mirrorURL, + Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. + Mirror: true, + TrimHostname: true, + TLSConfig: mirrorTLSConfig, + }) } endpoints = append(endpoints, APIEndpoint{ - URL: DefaultV2Registry, - Official: true, - TLSConfig: tlsconfig.ServerDefault(), + URL: DefaultV2Registry, + Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. + Official: true, + TrimHostname: true, + TLSConfig: tlsconfig.ServerDefault(), + + AllowNondistributableArtifacts: ana, }) return endpoints, nil @@ -50,7 +55,10 @@ func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]API Scheme: "https", Host: hostname, }, - TLSConfig: tlsConfig, + Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. + AllowNondistributableArtifacts: ana, + TrimHostname: true, + TLSConfig: tlsConfig, }, } @@ -60,6 +68,9 @@ func (s *Service) lookupV2Endpoints(hostname string, includeMirrors bool) ([]API Scheme: "http", Host: hostname, }, + Version: APIVersion2, //nolint:staticcheck // ignore SA1019 (Version is deprecated) to allow potential consumers to transition. + AllowNondistributableArtifacts: ana, + TrimHostname: true, // used to check if supposed to be secure via InsecureSkipVerify TLSConfig: tlsConfig, }) diff --git a/vendor/github.com/docker/docker/registry/types.go b/vendor/github.com/docker/docker/registry/types.go index 02d7f4f3..4926580a 100644 --- a/vendor/github.com/docker/docker/registry/types.go +++ b/vendor/github.com/docker/docker/registry/types.go @@ -5,6 +5,27 @@ import ( "github.com/docker/docker/api/types/registry" ) +// APIVersion is an integral representation of an API version (presently +// either 1 or 2) +// +// Deprecated: v1 registries are deprecated, and endpoints are always v2. +type APIVersion int + +func (av APIVersion) String() string { + return apiVersions[av] +} + +// API Version identifiers. +const ( + APIVersion1 APIVersion = 1 // Deprecated: v1 registries are deprecated, and endpoints are always v2. + APIVersion2 APIVersion = 2 // Deprecated: v1 registries are deprecated, and endpoints are always v2. +) + +var apiVersions = map[APIVersion]string{ + APIVersion1: "v1", + APIVersion2: "v2", +} + // RepositoryInfo describes a repository type RepositoryInfo struct { Name reference.Named diff --git a/vendor/modules.txt b/vendor/modules.txt index b7f12175..4f97936f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -282,7 +282,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 v28.0.0-rc.1+incompatible +# github.com/docker/docker v27.5.1+incompatible ## explicit github.com/docker/docker/api github.com/docker/docker/api/types @@ -295,7 +295,6 @@ github.com/docker/docker/api/types/image github.com/docker/docker/api/types/mount github.com/docker/docker/api/types/network github.com/docker/docker/api/types/registry -github.com/docker/docker/api/types/storage github.com/docker/docker/api/types/strslice github.com/docker/docker/api/types/swarm github.com/docker/docker/api/types/swarm/runtime @@ -305,17 +304,17 @@ github.com/docker/docker/api/types/versions github.com/docker/docker/api/types/volume github.com/docker/docker/client github.com/docker/docker/errdefs -github.com/docker/docker/internal/lazyregexp github.com/docker/docker/internal/multierror github.com/docker/docker/pkg/archive -github.com/docker/docker/pkg/atomicwriter github.com/docker/docker/pkg/homedir github.com/docker/docker/pkg/idtools github.com/docker/docker/pkg/ioutils github.com/docker/docker/pkg/jsonmessage github.com/docker/docker/pkg/namesgenerator +github.com/docker/docker/pkg/pools github.com/docker/docker/pkg/stdcopy github.com/docker/docker/pkg/stringid +github.com/docker/docker/pkg/system github.com/docker/docker/registry # github.com/docker/docker-credential-helpers v0.8.2 ## explicit; go 1.19 @@ -955,7 +954,7 @@ golang.org/x/tools/internal/stdlib golang.org/x/tools/internal/typeparams golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 +# google.golang.org/genproto/googleapis/api v0.0.0-20241007155032-5fefd90f89a9 ## explicit; go 1.21 google.golang.org/genproto/googleapis/api/httpbody # google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38