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>
This commit is contained in:
CrazyMax 2025-02-11 18:14:49 +01:00
parent 67dbde6970
commit cee7b344da
No known key found for this signature in database
GPG Key ID: ADE44D8C9D44FBE4
182 changed files with 3094 additions and 2915 deletions

View File

@ -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
}

View File

@ -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{} {

View File

@ -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 })

4
go.mod
View File

@ -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

8
go.sum
View File

@ -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=

View File

@ -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 {

View File

@ -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)

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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
@ -231,14 +239,7 @@ type PluginInstallOptions struct {
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)
PrivilegeFunc RequestPrivilegeFunc
AcceptPermissionsFunc func(context.Context, PluginPrivileges) (bool, error)
Args []string
}

View File

@ -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<foo>` 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"`
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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"`
@ -173,5 +165,17 @@ type StatsResponse struct {
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"`
}

View File

@ -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)
}

View File

@ -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.

View File

@ -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.
//

View File

@ -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"`
}

View File

@ -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
}

View File

@ -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.

View File

@ -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"`

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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 }

View File

@ -9,31 +9,13 @@ 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.
AllowNondistributableArtifactsCIDRs []*NetIPNet
AllowNondistributableArtifactsHostnames []string
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)
}
// NetIPNet is the net.IPNet type, which can be marshalled and
// unmarshalled to JSON
type NetIPNet net.IPNet

View File

@ -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

View File

@ -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.

View File

@ -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<foo>` 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.
@ -170,10 +482,8 @@ type BuildCache struct {
// BuildCachePruneOptions hold parameters to prune the build cache
type BuildCachePruneOptions struct {
All bool
ReservedSpace int64
MaxUsedSpace int64
MinFreeSpace int64
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
}

View File

@ -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
}

View File

@ -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)))
}
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")
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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"},
})
}

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}
var changes []container.FilesystemChange
err = json.NewDecoder(serverResp.body).Decode(&changes)
if err != nil {
return nil, err
}
return changes, err
}
err = json.NewDecoder(serverResp.body).Decode(&changes)
return changes, err
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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)

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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")

View File

@ -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))

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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.
//

View File

@ -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)
}

View File

@ -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

View File

@ -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)
}
if options.NetworkMode != "" && options.NetworkMode != network.NetworkDefault {
query.Set("networkmode", options.NetworkMode)
}
if options.CPUSetMems != "" {
query.Set("cpusetmems", options.CPUSetMems)
}
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))
}
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))
}
if options.Outputs != nil {
outputsJSON, err := json.Marshal(options.Outputs)

View File

@ -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
}

View File

@ -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)
}
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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

View File

@ -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{}

View File

@ -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,

View File

@ -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,

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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")

View File

@ -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)

View File

@ -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

View File

@ -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")

View File

@ -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))

View File

@ -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)

View File

@ -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},
})

View File

@ -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")

View File

@ -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

View File

@ -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
}

View File

@ -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))
}
} 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")

View File

@ -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 {

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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")

View File

@ -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

View File

@ -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)

View File

@ -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 {

View File

@ -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
}

View File

@ -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

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