Merge pull request #6593 from thaJeztah/bump_modules

vendor: github.com/moby/moby/api master, moby/client master
This commit is contained in:
Austin Vazquez
2025-10-30 22:45:41 -05:00
committed by GitHub
42 changed files with 370 additions and 205 deletions

View File

@ -139,7 +139,7 @@ func withPluginClientConn(name string) command.CLIOption {
if err != nil {
return err
}
apiClient, err := client.NewClientWithOpts(client.WithDialContext(helper.Dialer))
apiClient, err := client.New(client.WithDialContext(helper.Dialer))
if err != nil {
return err
}

View File

@ -316,7 +316,7 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
opts = append(opts, withCustomHeaders)
}
opts = append(opts, extraOpts...)
return client.NewClientWithOpts(opts...)
return client.New(opts...)
}
func resolveDockerEndpoint(s store.Reader, contextName string) (docker.Endpoint, error) {

View File

@ -292,7 +292,7 @@ func TestNewDockerCliAndOperators(t *testing.T) {
func TestInitializeShouldAlwaysCreateTheContextStore(t *testing.T) {
cli, err := NewDockerCli()
assert.NilError(t, err)
apiClient, err := client.NewClientWithOpts()
apiClient, err := client.New()
assert.NilError(t, err)
assert.NilError(t, cli.Initialize(flags.NewClientOptions(), WithAPIClient(apiClient)))
assert.Check(t, cli.ContextStore() != nil)

View File

@ -135,9 +135,14 @@ func pullImage(ctx context.Context, dockerCli command.Cli, img string, options *
return err
}
var ociPlatforms []ocispec.Platform
if options.platform != "" {
// Already validated.
ociPlatforms = append(ociPlatforms, platforms.MustParse(options.platform))
}
resp, err := dockerCli.Client().ImageCreate(ctx, img, client.ImageCreateOptions{
RegistryAuth: encodedAuth,
Platform: options.platform,
Platforms: ociPlatforms,
})
if err != nil {
return err
@ -213,6 +218,14 @@ func createContainer(ctx context.Context, dockerCli command.Cli, containerCfg *c
namedRef reference.Named
)
// TODO(thaJeztah): add a platform option-type / flag-type.
if options.platform != "" {
_, err = platforms.Parse(options.platform)
if err != nil {
return "", err
}
}
containerIDFile, err := newCIDFile(hostConfig.ContainerIDFile)
if err != nil {
return "", err

View File

@ -885,10 +885,11 @@ func parseNetworkAttachmentOpt(ep opts.NetworkAttachmentOpts) (*network.Endpoint
}
}
if ep.MacAddress != "" {
if _, err := net.ParseMAC(strings.TrimSpace(ep.MacAddress)); err != nil {
ma, err := net.ParseMAC(strings.TrimSpace(ep.MacAddress))
if err != nil {
return nil, fmt.Errorf("%s is not a valid mac address", ep.MacAddress)
}
epConfig.MacAddress = ep.MacAddress
epConfig.MacAddress = network.HardwareAddr(ma)
}
return epConfig, nil
}

View File

@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"io"
"net"
"net/netip"
"os"
"runtime"
@ -20,6 +21,14 @@ import (
"gotest.tools/v3/skip"
)
func mustParseMAC(s string) networktypes.HardwareAddr {
mac, err := net.ParseMAC(s)
if err != nil {
panic(err)
}
return networktypes.HardwareAddr(mac)
}
func TestValidateAttach(t *testing.T) {
valid := []string{
"stdin",
@ -353,7 +362,7 @@ func TestParseWithMacAddress(t *testing.T) {
}
_, hostConfig, nwConfig := mustParse(t, validMacAddress)
defaultNw := hostConfig.NetworkMode.NetworkName()
if nwConfig.EndpointsConfig[defaultNw].MacAddress != "92:d0:c6:0a:29:33" {
if nwConfig.EndpointsConfig[defaultNw].MacAddress.String() != "92:d0:c6:0a:29:33" {
t.Fatalf("Expected the default endpoint to have the MacAddress '92:d0:c6:0a:29:33' set, got '%v'", nwConfig.EndpointsConfig[defaultNw].MacAddress)
}
}
@ -650,7 +659,7 @@ func TestParseNetworkConfig(t *testing.T) {
Aliases: []string{"web3"},
},
"net4": {
MacAddress: "02:32:1c:23:00:04",
MacAddress: mustParseMAC("02:32:1c:23:00:04"),
IPAMConfig: &networktypes.EndpointIPAMConfig{
LinkLocalIPs: []netip.Addr{netip.MustParseAddr("169.254.169.254")},
},
@ -672,7 +681,7 @@ func TestParseNetworkConfig(t *testing.T) {
IPv6Address: netip.MustParseAddr("2001:db8::8822"),
},
Aliases: []string{"web1", "web2"},
MacAddress: "02:32:1c:23:00:04",
MacAddress: mustParseMAC("02:32:1c:23:00:04"),
},
},
expectedHostCfg: container.HostConfig{NetworkMode: "net1"},
@ -689,7 +698,7 @@ func TestParseNetworkConfig(t *testing.T) {
expected: map[string]*networktypes.EndpointSettings{
"net1": {
Aliases: []string{"foobar"},
MacAddress: "52:0f:f3:dc:50:10",
MacAddress: mustParseMAC("52:0f:f3:dc:50:10"),
},
},
expectedHostCfg: container.HostConfig{NetworkMode: "net1"},

View File

@ -123,7 +123,7 @@ func getDockerEndpoint(contextStore store.Reader, config map[string]string) (doc
return docker.Endpoint{}, fmt.Errorf("invalid docker endpoint options: %w", err)
}
// FIXME(thaJeztah): this creates a new client (but discards it) only to validate the options; are the validation steps above not enough?
if _, err := client.NewClientWithOpts(opts...); err != nil {
if _, err := client.New(opts...); err != nil {
return docker.Endpoint{}, fmt.Errorf("unable to apply docker endpoint options: %w", err)
}
return ep, nil

View File

@ -11,6 +11,7 @@ import (
"path/filepath"
"strings"
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/cli-docs-tool/annotation"
"github.com/docker/cli/cli"
@ -27,6 +28,7 @@ import (
"github.com/moby/moby/client"
"github.com/moby/moby/client/pkg/progress"
"github.com/moby/moby/client/pkg/streamformatter"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
)
@ -190,6 +192,13 @@ func runBuild(ctx context.Context, dockerCli command.Cli, options buildOptions)
remote string
)
if options.platform != "" {
_, err := platforms.Parse(options.platform)
if err != nil {
return err
}
}
contextType, err := build.DetectContextType(options.context)
if err != nil {
return err
@ -399,6 +408,12 @@ func validateTag(rawRepo string) (string, error) {
func imageBuildOptions(dockerCli command.Cli, options buildOptions) client.ImageBuildOptions {
configFile := dockerCli.ConfigFile()
var buildPlatforms []ocispec.Platform
if options.platform != "" {
// Already validated.
buildPlatforms = append(buildPlatforms, platforms.MustParse(options.platform))
}
return client.ImageBuildOptions{
Version: buildtypes.BuilderV1,
Memory: options.memory.Value(),
@ -426,6 +441,6 @@ func imageBuildOptions(dockerCli command.Cli, options buildOptions) client.Image
Squash: options.squash,
ExtraHosts: options.extraHosts.GetSlice(),
Target: options.target,
Platform: options.platform,
Platforms: buildPlatforms,
}
}

View File

@ -5,12 +5,14 @@ import (
"os"
"strings"
"github.com/containerd/platforms"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/completion"
"github.com/docker/cli/internal/jsonstream"
dockeropts "github.com/docker/cli/opts"
"github.com/moby/moby/client"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
)
@ -82,10 +84,20 @@ func runImport(ctx context.Context, dockerCli command.Cli, options importOptions
}
}
// TODO(thaJeztah): add a platform option-type / flag-type.
var ociPlatform ocispec.Platform
if options.platform != "" {
var err error
ociPlatform, err = platforms.Parse(options.platform)
if err != nil {
return err
}
}
responseBody, err := dockerCli.Client().ImageImport(ctx, source, options.reference, client.ImageImportOptions{
Message: options.message,
Changes: options.changes.GetSlice(),
Platform: options.platform,
Platform: ociPlatform,
})
if err != nil {
return err

View File

@ -7,6 +7,7 @@ import (
"io"
"os"
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
@ -17,6 +18,7 @@ import (
"github.com/moby/moby/api/pkg/authconfig"
registrytypes "github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/spf13/cobra"
)
@ -78,6 +80,13 @@ func runPull(ctx context.Context, dockerCLI command.Cli, opts pullOptions) error
}
}
if opts.platform != "" {
// TODO(thaJeztah): add a platform option-type / flag-type.
if _, err = platforms.Parse(opts.platform); err != nil {
return err
}
}
imgRefAndAuth, err := trust.GetImageReferencesAndAuth(ctx, authResolver(dockerCLI), distributionRef.String())
if err != nil {
return err
@ -104,11 +113,17 @@ func imagePullPrivileged(ctx context.Context, dockerCLI command.Cli, ref referen
if err != nil {
return err
}
var ociPlatforms []ocispec.Platform
if opts.platform != "" {
// Already validated.
ociPlatforms = append(ociPlatforms, platforms.MustParse(opts.platform))
}
responseBody, err := dockerCLI.Client().ImagePull(ctx, reference.FamiliarString(ref), client.ImagePullOptions{
RegistryAuth: encodedAuth,
PrivilegeFunc: nil,
All: opts.all,
Platform: opts.platform,
Platforms: ociPlatforms,
})
if err != nil {
return err

View File

@ -173,7 +173,7 @@ func loginWithStoredCredentials(ctx context.Context, dockerCLI command.Cli, auth
} else {
_, _ = fmt.Fprintln(dockerCLI.Err(), "Login did not succeed, error:", err)
}
// TODO(thaJeztah): should this return the error here, or is there a reasong for continuing?
// TODO(thaJeztah): should this return the error here, or is there a reason for continuing?
}
if resp.Auth.IdentityToken != "" {

View File

@ -5,7 +5,6 @@ import (
"strings"
"github.com/docker/cli/cli/compose/convert"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/network"
"github.com/moby/moby/api/types/swarm"
"github.com/moby/moby/client"
@ -38,9 +37,8 @@ type fakeClient struct {
configRemoveFunc func(configID string) (client.ConfigRemoveResult, error)
}
func (*fakeClient) ServerVersion(context.Context) (types.Version, error) {
return types.Version{
Version: "docker-dev",
func (*fakeClient) ServerVersion(context.Context, client.ServerVersionOptions) (client.ServerVersionResult, error) {
return client.ServerVersionResult{
APIVersion: client.MaxAPIVersion,
}, nil
}

View File

@ -3,7 +3,6 @@ package system
import (
"context"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/events"
"github.com/moby/moby/client"
@ -21,7 +20,7 @@ type fakeClient struct {
networkListFunc func(ctx context.Context, options client.NetworkListOptions) (client.NetworkListResult, error)
networkPruneFunc func(ctx context.Context, options client.NetworkPruneOptions) (client.NetworkPruneResult, error)
nodeListFunc func(ctx context.Context, options client.NodeListOptions) (client.NodeListResult, error)
serverVersion func(ctx context.Context) (types.Version, error)
serverVersion func(ctx context.Context, options client.ServerVersionOptions) (client.ServerVersionResult, error)
volumeListFunc func(ctx context.Context, options client.VolumeListOptions) (client.VolumeListResult, error)
}
@ -89,8 +88,8 @@ func (cli *fakeClient) NodeList(ctx context.Context, options client.NodeListOpti
return client.NodeListResult{}, nil
}
func (cli *fakeClient) ServerVersion(ctx context.Context) (types.Version, error) {
return cli.serverVersion(ctx)
func (cli *fakeClient) ServerVersion(ctx context.Context, options client.ServerVersionOptions) (client.ServerVersionResult, error) {
return cli.serverVersion(ctx, options)
}
func (cli *fakeClient) VolumeList(ctx context.Context, options client.VolumeListOptions) (client.VolumeListResult, error) {

View File

@ -1 +1 @@
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"","APIVersion":"","MinAPIVersion":"","Os":"","Arch":"","Experimental":false,"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}]}}

View File

@ -1 +1 @@
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}],"Version":"","ApiVersion":"","GitCommit":"","GoVersion":"","Os":"","Arch":""}}
{"Client":{"Version":"18.99.5-ce","ApiVersion":"1.38","DefaultAPIVersion":"1.38","GitCommit":"deadbeef","GoVersion":"go1.10.2","Os":"linux","Arch":"amd64","BuildTime":"Wed May 30 22:21:05 2018","Context":"my-context"},"Server":{"Platform":{"Name":"Docker Enterprise Edition (EE) 2.0"},"Version":"","APIVersion":"","MinAPIVersion":"","Os":"","Arch":"","Experimental":false,"Components":[{"Name":"Engine","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 9 23:38:38 2018","Experimental":"false","GitCommit":"64ddfa6","GoVersion":"go1.8.7","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"Universal Control Plane","Version":"17.06.2-ee-15","Details":{"ApiVersion":"1.30","Arch":"amd64","BuildTime":"Mon Jul 2 21:24:07 UTC 2018","GitCommit":"4513922","GoVersion":"go1.9.4","MinApiVersion":"1.20","Os":"linux","Version":"3.0.3-tp2"}},{"Name":"Kubernetes","Version":"1.8+","Details":{"buildDate":"2018-04-26T16:51:21Z","compiler":"gc","gitCommit":"8d637aedf46b9c21dde723e29c645b9f27106fa5","gitTreeState":"clean","gitVersion":"v1.8.11-docker-8d637ae","goVersion":"go1.8.3","major":"1","minor":"8+","platform":"linux/amd64"}},{"Name":"Calico","Version":"v3.0.8","Details":{"cni":"v2.0.6","kube-controllers":"v2.0.5","node":"v3.0.8"}}]}}

View File

@ -6,7 +6,6 @@ import (
"io"
"runtime"
"sort"
"strconv"
"text/template"
"time"
@ -17,7 +16,7 @@ import (
flagsHelper "github.com/docker/cli/cli/flags"
"github.com/docker/cli/cli/version"
"github.com/docker/cli/templates"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/client"
"github.com/spf13/cobra"
"github.com/tonistiigi/go-rosetta"
@ -64,7 +63,7 @@ type versionOptions struct {
// versionInfo contains version information of both the Client, and Server
type versionInfo struct {
Client clientVersion
Server *types.Version
Server *client.ServerVersionResult
}
type platformInfo struct {
@ -153,12 +152,10 @@ func runVersion(ctx context.Context, dockerCli command.Cli, opts *versionOptions
return cli.StatusError{StatusCode: 64, Status: err.Error()}
}
// TODO print error if kubernetes is used?
vd := versionInfo{
Client: newClientVersion(dockerCli.CurrentContext(), dockerCli),
}
sv, err := dockerCli.Client().ServerVersion(ctx)
sv, err := dockerCli.Client().ServerVersion(ctx, client.ServerVersionOptions{})
if err == nil {
vd.Server = &sv
foundEngine := false
@ -173,18 +170,14 @@ func runVersion(ctx context.Context, dockerCli command.Cli, opts *versionOptions
}
if !foundEngine {
vd.Server.Components = append(vd.Server.Components, types.ComponentVersion{
vd.Server.Components = append(vd.Server.Components, system.ComponentVersion{
Name: "Engine",
Version: sv.Version,
Details: map[string]string{
"ApiVersion": sv.APIVersion,
"MinAPIVersion": sv.MinAPIVersion,
"GitCommit": sv.GitCommit,
"GoVersion": sv.GoVersion,
"Os": sv.Os,
"Arch": sv.Arch,
"BuildTime": reformatDate(vd.Server.BuildTime),
"Experimental": strconv.FormatBool(sv.Experimental),
},
})
}
@ -217,7 +210,7 @@ func newVersionTemplate(templateFormat string) (*template.Template, error) {
return tmpl, nil
}
func getDetailsOrder(v types.ComponentVersion) []string {
func getDetailsOrder(v system.ComponentVersion) []string {
out := make([]string, 0, len(v.Details))
for k := range v.Details {
out = append(out, k)

View File

@ -9,7 +9,8 @@ import (
"testing"
"github.com/docker/cli/internal/test"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/system"
"github.com/moby/moby/client"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
"gotest.tools/v3/golden"
@ -17,8 +18,8 @@ import (
func TestVersionWithoutServer(t *testing.T) {
cli := test.NewFakeCli(&fakeClient{
serverVersion: func(ctx context.Context) (types.Version, error) {
return types.Version{}, errors.New("no server")
serverVersion: func(ctx context.Context, options client.ServerVersionOptions) (client.ServerVersionResult, error) {
return client.ServerVersionResult{}, errors.New("no server")
},
})
cmd := newVersionCommand(cli)
@ -46,9 +47,9 @@ func TestVersionFormat(t *testing.T) {
BuildTime: "Wed May 30 22:21:05 2018",
Context: "my-context",
},
Server: &types.Version{
Platform: struct{ Name string }{Name: "Docker Enterprise Edition (EE) 2.0"},
Components: []types.ComponentVersion{
Server: &client.ServerVersionResult{
Platform: client.PlatformInfo{Name: "Docker Enterprise Edition (EE) 2.0"},
Components: []system.ComponentVersion{
{
Name: "Engine",
Version: "17.06.2-ee-15",

View File

@ -11,8 +11,8 @@ import (
type (
JSONError = jsonstream.Error
JSONMessage = jsonmessage.JSONMessage
JSONProgress = jsonmessage.JSONProgress
JSONMessage = jsonstream.Message
JSONProgress = jsonstream.Progress
)
type ctxReader struct {

View File

@ -33,12 +33,10 @@ func TestDisplay(t *testing.T) {
err := enc.Encode(JSONMessage{
Status: "Downloading",
ID: fmt.Sprintf("id-%d", i),
Progress: &JSONProgress{
Progress: jsonstream.Progress{
Current: int64(i),
Total: 100,
Start: 0,
},
Progress: &jsonstream.Progress{
Current: int64(i),
Total: 100,
Start: 0,
},
})
if err != nil {

View File

@ -28,8 +28,8 @@ require (
github.com/google/uuid v1.6.0
github.com/mattn/go-runewidth v0.0.17
github.com/moby/go-archive v0.1.0
github.com/moby/moby/api v1.52.0-beta.2.0.20251029225139-7a97e1cb401f // master
github.com/moby/moby/client v0.1.0-beta.2.0.20251029225139-7a97e1cb401f // master
github.com/moby/moby/api v1.52.0-beta.3.0.20251031021517-d96f50518f8d // master
github.com/moby/moby/client v0.1.0-beta.2.0.20251031021517-d96f50518f8d // master
github.com/moby/patternmatcher v0.6.0
github.com/moby/swarmkit/v2 v2.1.0
github.com/moby/sys/atomicwriter v0.1.0

View File

@ -170,10 +170,10 @@ github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3N
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
github.com/moby/go-archive v0.1.0 h1:Kk/5rdW/g+H8NHdJW2gsXyZ7UnzvJNOy6VKJqueWdcQ=
github.com/moby/go-archive v0.1.0/go.mod h1:G9B+YoujNohJmrIYFBpSd54GTUB4lt9S+xVQvsJyFuo=
github.com/moby/moby/api v1.52.0-beta.2.0.20251029225139-7a97e1cb401f h1:agkZxo7k3fXBqdq6leYCCv0K45OjkH/H3fzPjwcoDkY=
github.com/moby/moby/api v1.52.0-beta.2.0.20251029225139-7a97e1cb401f/go.mod h1:v0K/motq8oWmx+rtApG1rBTIpQ8KUONUjpf+U73gags=
github.com/moby/moby/client v0.1.0-beta.2.0.20251029225139-7a97e1cb401f h1:I0uikdmKsCbOxQV+DIn7gyY8bD0d19g8920FuxI9l3E=
github.com/moby/moby/client v0.1.0-beta.2.0.20251029225139-7a97e1cb401f/go.mod h1:1YrJTvhL771Q4xiwwe72NSS17lgsCF67xu8fEfSd77g=
github.com/moby/moby/api v1.52.0-beta.3.0.20251031021517-d96f50518f8d h1:yv97052L6n+B7nwsJSms4aC8qDJcFKEuAoyNQAjJcUg=
github.com/moby/moby/api v1.52.0-beta.3.0.20251031021517-d96f50518f8d/go.mod h1:v0K/motq8oWmx+rtApG1rBTIpQ8KUONUjpf+U73gags=
github.com/moby/moby/client v0.1.0-beta.2.0.20251031021517-d96f50518f8d h1:wXNr/8nLcBwLH9RujUs3KgAxmGkpQ0AvQlTAnVaigoA=
github.com/moby/moby/client v0.1.0-beta.2.0.20251031021517-d96f50518f8d/go.mod h1:1YrJTvhL771Q4xiwwe72NSS17lgsCF67xu8fEfSd77g=
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/swarmkit/v2 v2.1.0 h1:u+cJ5hSyF3HnzsyI+NtegYxdIPQIuibk7IbpXNxuISM=

View File

@ -30,7 +30,7 @@ type EndpointSettings struct {
// MacAddress may be used to specify a MAC address when the container is created.
// Once the container is running, it becomes operational data (it may contain a
// generated address).
MacAddress string
MacAddress HardwareAddr
IPPrefixLen int
IPv6Gateway netip.Addr
GlobalIPv6Address netip.Addr

View File

@ -24,7 +24,7 @@ type EndpointResource struct {
// mac address
// Example: 02:42:ac:13:00:02
MacAddress string `json:"MacAddress"`
MacAddress HardwareAddr `json:"MacAddress"`
// IPv4 address
// Example: 172.19.0.2/16

View File

@ -0,0 +1,37 @@
package network
import (
"encoding"
"fmt"
"net"
)
// A HardwareAddr represents a physical hardware address.
// It implements [encoding.TextMarshaler] and [encoding.TextUnmarshaler]
// in the absence of go.dev/issue/29678.
type HardwareAddr net.HardwareAddr
var _ encoding.TextMarshaler = (HardwareAddr)(nil)
var _ encoding.TextUnmarshaler = (*HardwareAddr)(nil)
var _ fmt.Stringer = (HardwareAddr)(nil)
func (m *HardwareAddr) UnmarshalText(text []byte) error {
if len(text) == 0 {
*m = nil
return nil
}
hw, err := net.ParseMAC(string(text))
if err != nil {
return err
}
*m = HardwareAddr(hw)
return nil
}
func (m HardwareAddr) MarshalText() ([]byte, error) {
return []byte(net.HardwareAddr(m).String()), nil
}
func (m HardwareAddr) String() string {
return net.HardwareAddr(m).String()
}

View File

@ -0,0 +1,58 @@
package system
// VersionResponse contains information about the Docker server host.
// GET "/version"
type VersionResponse struct {
// Platform is the platform (product name) the server is running on.
Platform PlatformInfo `json:",omitempty"`
// Version is the version of the daemon.
Version string
// APIVersion is the highest API version supported by the server.
APIVersion string `json:"ApiVersion"`
// MinAPIVersion is the minimum API version the server supports.
MinAPIVersion string `json:"MinAPIVersion,omitempty"`
// Os is the operating system the server runs on.
Os string
// Arch is the hardware architecture the server runs on.
Arch string
// Components contains version information for the components making
// up the server. Information in this field is for informational
// purposes, and not part of the API contract.
Components []ComponentVersion `json:",omitempty"`
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
GitCommit string `json:",omitempty"`
GoVersion string `json:",omitempty"`
KernelVersion string `json:",omitempty"`
Experimental bool `json:",omitempty"`
BuildTime string `json:",omitempty"`
}
// PlatformInfo holds information about the platform (product name) the
// server is running on.
type PlatformInfo struct {
// Name is the name of the platform (for example, "Docker Engine - Community",
// or "Docker Desktop 4.49.0 (208003)")
Name string
}
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
Name string
Version string
// Details contains Key/value pairs of strings with additional information
// about the component. These values are intended for informational purposes
// only, and their content is not defined, and not part of the API
// specification.
//
// These messages can be printed by the client as information to the user.
Details map[string]string `json:",omitempty"`
}

View File

@ -16,39 +16,3 @@ const (
// MediaTypeJSONSequence is the MIME-Type for JSON Text Sequences (RFC7464).
MediaTypeJSONSequence = "application/json-seq"
)
// ComponentVersion describes the version information for a specific component.
type ComponentVersion struct {
Name string
Version string
Details map[string]string `json:",omitempty"`
}
// Version contains response of Engine API:
// GET "/version"
type Version struct {
Platform struct{ Name string } `json:",omitempty"`
Components []ComponentVersion `json:",omitempty"`
// The following fields are deprecated, they relate to the Engine component and are kept for backwards compatibility
Version string
APIVersion string `json:"ApiVersion"`
MinAPIVersion string `json:"MinAPIVersion,omitempty"`
GitCommit string
GoVersion string
Os string
Arch string
KernelVersion string `json:",omitempty"`
Experimental bool `json:",omitempty"`
BuildTime string `json:",omitempty"`
}
// PushResult contains the tag, manifest digest, and manifest size from the
// push. It's used to signal this information to the trust code in the client
// so it can sign the manifest if necessary.
type PushResult struct {
Tag string
Digest string
Size int
}

View File

@ -23,7 +23,7 @@ import (
)
func main() {
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
apiClient, err := client.New(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
panic(err)
}

View File

@ -6,7 +6,7 @@ https://docs.docker.com/reference/api/engine/
# Usage
You use the library by constructing a client object using [NewClientWithOpts]
You use the library by constructing a client object using [New]
and calling methods on it. The client can be configured from environment
variables by passing the [FromEnv] option, and the [WithAPIVersionNegotiation]
option to allow downgrading the API version used when connecting with an older
@ -30,7 +30,7 @@ For example, to list running containers (the equivalent of "docker ps"):
// for configuration (DOCKER_HOST, DOCKER_API_VERSION), and does
// API-version negotiation to allow downgrading the API version
// when connecting with an older daemon version.
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
apiClient, err := client.New(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
log.Fatal(err)
}
@ -160,7 +160,14 @@ func CheckRedirect(_ *http.Request, via []*http.Request) error {
return ErrRedirect
}
// NewClientWithOpts initializes a new API client with a default HTTPClient, and
// NewClientWithOpts initializes a new API client.
//
// Deprecated: use New. This function will be removed in the next release.
func NewClientWithOpts(ops ...Opt) (*Client, error) {
return New(ops...)
}
// New initializes a new API client with a default HTTPClient, and
// default API host and version. It also initializes the custom HTTP headers to
// add to each request.
//
@ -170,11 +177,11 @@ func CheckRedirect(_ *http.Request, via []*http.Request) error {
// itself with values from environment variables ([FromEnv]), and has automatic
// API version negotiation enabled ([WithAPIVersionNegotiation]).
//
// cli, err := client.NewClientWithOpts(
// cli, err := client.New(
// client.FromEnv,
// client.WithAPIVersionNegotiation(),
// )
func NewClientWithOpts(ops ...Opt) (*Client, error) {
func New(ops ...Opt) (*Client, error) {
hostURL, err := ParseHostURL(DefaultDockerHost)
if err != nil {
return nil, err

View File

@ -5,7 +5,6 @@ import (
"io"
"net"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/network"
"github.com/moby/moby/api/types/system"
)
@ -27,7 +26,7 @@ type stableAPIClient interface {
VolumeAPIClient
ClientVersion() string
DaemonHost() string
ServerVersion(ctx context.Context) (types.Version, error)
ServerVersion(ctx context.Context, options ServerVersionOptions) (ServerVersionResult, error)
HijackDialer
Dialer() func(context.Context) (net.Conn, error)
Close() error

View File

@ -8,8 +8,8 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
cerrdefs "github.com/containerd/errdefs"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/network"
)
@ -154,8 +154,12 @@ func (cli *Client) imageBuildOptionsToQuery(_ context.Context, options ImageBuil
if options.SessionID != "" {
query.Set("session", options.SessionID)
}
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
if len(options.Platforms) > 0 {
if len(options.Platforms) > 1 {
// TODO(thaJeztah): update API spec and add equivalent check on the daemon. We need this still for older daemons, which would ignore it.
return query, cerrdefs.ErrInvalidArgument.WithMessage("specifying multiple platforms is not yet supported")
}
query.Set("platform", formatPlatform(options.Platforms[0]))
}
if options.BuildID != "" {
query.Set("buildid", options.BuildID)

View File

@ -6,6 +6,7 @@ import (
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/registry"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageBuildOptions holds the information
@ -50,7 +51,9 @@ type ImageBuildOptions struct {
ExtraHosts []string // List of extra hosts
Target string
SessionID string
Platform string
// Platforms selects the platforms to build the image for. Multiple platforms
// can be provided if the daemon supports multi-platform builds.
Platforms []ocispec.Platform
// Version specifies the version of the underlying builder to use
Version build.BuilderVersion
// BuildID is an optional identifier that can be passed together with the

View File

@ -4,8 +4,8 @@ import (
"context"
"net/http"
"net/url"
"strings"
cerrdefs "github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/moby/moby/api/types/registry"
)
@ -21,8 +21,12 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
query := url.Values{}
query.Set("fromImage", ref.Name())
query.Set("tag", getAPITagFromNamedRef(ref))
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
if len(options.Platforms) > 0 {
if len(options.Platforms) > 1 {
// TODO(thaJeztah): update API spec and add equivalent check on the daemon. We need this still for older daemons, which would ignore it.
return ImageCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("specifying multiple platforms is not yet supported")
}
query.Set("platform", formatPlatform(options.Platforms[0]))
}
resp, err := cli.tryImageCreate(ctx, query, staticAuth(options.RegistryAuth))
if err != nil {

View File

@ -1,11 +1,18 @@
package client
import "io"
import (
"io"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageCreateOptions holds information to create images.
type ImageCreateOptions struct {
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
// Platforms specifies the platforms to platform of the image if it needs
// to be pulled from the registry. Multiple platforms can be provided
// if the daemon supports multi-platform pulls.
Platforms []ocispec.Platform
}
// ImageCreateResult holds the response body returned by the daemon for image create.

View File

@ -3,7 +3,6 @@ package client
import (
"context"
"net/url"
"strings"
"github.com/distribution/reference"
)
@ -31,8 +30,9 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re
if options.Message != "" {
query.Set("message", options.Message)
}
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
if p := formatPlatform(options.Platform); p != "unknown" {
// TODO(thaJeztah): would we ever support mutiple platforms here? (would require multiple rootfs tars as well?)
query.Set("platform", p)
}
for _, change := range options.Changes {
query.Add("changes", change)

View File

@ -2,6 +2,8 @@ package client
import (
"io"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageImportSource holds source information for ImageImport
@ -12,10 +14,10 @@ type ImageImportSource struct {
// ImageImportOptions holds information to import images from the client host.
type ImageImportOptions struct {
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
Platform string // Platform is the target platform of the image
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
Message string // Message is the message to tag the image with
Changes []string // Changes are the raw changes to apply to this image
Platform ocispec.Platform // Platform is the target platform of the image
}
// ImageImportResult holds the response body returned by the daemon for image import.

View File

@ -5,17 +5,16 @@ import (
"io"
"iter"
"net/url"
"strings"
cerrdefs "github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/moby/moby/api/types/jsonstream"
"github.com/moby/moby/client/internal"
"github.com/moby/moby/client/pkg/jsonmessage"
)
type ImagePullResponse interface {
io.ReadCloser
JSONMessages(ctx context.Context) iter.Seq2[jsonmessage.JSONMessage, error]
JSONMessages(ctx context.Context) iter.Seq2[jsonstream.Message, error]
Wait(ctx context.Context) error
}
@ -44,10 +43,13 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options ImagePu
if !options.All {
query.Set("tag", getAPITagFromNamedRef(ref))
}
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))
if len(options.Platforms) > 0 {
if len(options.Platforms) > 1 {
// TODO(thaJeztah): update API spec and add equivalent check on the daemon. We need this still for older daemons, which would ignore it.
return nil, cerrdefs.ErrInvalidArgument.WithMessage("specifying multiple platforms is not yet supported")
}
query.Set("platform", formatPlatform(options.Platforms[0]))
}
resp, err := cli.tryImageCreate(ctx, query, staticAuth(options.RegistryAuth))
if cerrdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
resp, err = cli.tryImageCreate(ctx, query, options.PrivilegeFunc)

View File

@ -2,6 +2,8 @@ package client
import (
"context"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImagePullOptions holds information to pull images.
@ -16,5 +18,8 @@ type ImagePullOptions struct {
//
// For details, refer to [github.com/moby/moby/api/types/registry.RequestAuthConfig].
PrivilegeFunc func(context.Context) (string, error)
Platform string
// Platforms selects the platforms to pull. Multiple platforms can be
// specified if the image ia a multi-platform image.
Platforms []ocispec.Platform
}

View File

@ -12,14 +12,14 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/distribution/reference"
"github.com/moby/moby/api/types/jsonstream"
"github.com/moby/moby/api/types/registry"
"github.com/moby/moby/client/internal"
"github.com/moby/moby/client/pkg/jsonmessage"
)
type ImagePushResponse interface {
io.ReadCloser
JSONMessages(ctx context.Context) iter.Seq2[jsonmessage.JSONMessage, error]
JSONMessages(ctx context.Context) iter.Seq2[jsonstream.Message, error]
Wait(ctx context.Context) error
}

View File

@ -8,7 +8,7 @@ import (
"iter"
"sync"
"github.com/moby/moby/client/pkg/jsonmessage"
"github.com/moby/moby/api/types/jsonstream"
)
func NewJSONMessageStream(rc io.ReadCloser) stream {
@ -44,15 +44,15 @@ func (r stream) Close() error {
// JSONMessages decodes the response stream as a sequence of JSONMessages.
// if stream ends or context is cancelled, the underlying [io.Reader] is closed.
func (r stream) JSONMessages(ctx context.Context) iter.Seq2[jsonmessage.JSONMessage, error] {
func (r stream) JSONMessages(ctx context.Context) iter.Seq2[jsonstream.Message, error] {
context.AfterFunc(ctx, func() {
_ = r.Close()
})
dec := json.NewDecoder(r)
return func(yield func(jsonmessage.JSONMessage, error) bool) {
return func(yield func(jsonstream.Message, error) bool) {
defer r.Close()
for {
var jm jsonmessage.JSONMessage
var jm jsonstream.Message
err := dec.Decode(&jm)
if errors.Is(err, io.EOF) {
break

View File

@ -14,28 +14,14 @@ import (
"github.com/moby/term"
)
var timeNow = time.Now // For overriding in tests.
// RFC3339NanoFixed is time.RFC3339Nano with nanoseconds padded using zeros to
// ensure the formatted time isalways the same number of characters.
const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
// JSONProgress describes a progress message in a JSON stream.
type JSONProgress struct {
jsonstream.Progress
// terminalFd is the fd of the current terminal, if any. It is used
// to get the terminal width.
terminalFd uintptr
// nowFunc is used to override the current time in tests.
nowFunc func() time.Time
// winSize is used to override the terminal width in tests.
winSize int
}
func (p *JSONProgress) String() string {
func RenderTUIProgress(p jsonstream.Progress, width uint16) string {
var (
width = p.width()
pbBox string
numbersBox string
)
@ -89,7 +75,7 @@ func (p *JSONProgress) String() string {
var timeLeftBox string
if width > 50 {
if p.Current > 0 && p.Start > 0 && percentage < 50 {
fromStart := p.now().Sub(time.Unix(p.Start, 0))
fromStart := timeNow().UTC().Sub(time.Unix(p.Start, 0))
perEntry := fromStart / time.Duration(p.Current)
left := time.Duration(p.Total-p.Current) * perEntry
timeLeftBox = " " + left.Round(time.Second).String()
@ -98,40 +84,6 @@ func (p *JSONProgress) String() string {
return pbBox + numbersBox + timeLeftBox
}
// now returns the current time in UTC, but can be overridden in tests
// by setting JSONProgress.nowFunc to a custom function.
func (p *JSONProgress) now() time.Time {
if p.nowFunc != nil {
return p.nowFunc()
}
return time.Now().UTC()
}
// width returns the current terminal's width, but can be overridden
// in tests by setting JSONProgress.winSize to a non-zero value.
func (p *JSONProgress) width() int {
if p.winSize != 0 {
return p.winSize
}
ws, err := term.GetWinsize(p.terminalFd)
if err == nil {
return int(ws.Width)
}
return 200
}
// JSONMessage defines a message struct. It describes
// the created time, where it from, status, ID of the
// message. It's used for docker events.
type JSONMessage struct {
Stream string `json:"stream,omitempty"`
Status string `json:"status,omitempty"`
Progress *JSONProgress `json:"progressDetail,omitempty"`
ID string `json:"id,omitempty"`
Error *jsonstream.Error `json:"errorDetail,omitempty"`
Aux *json.RawMessage `json:"aux,omitempty"` // Aux contains out-of-band data, such as digests for push signing and image id after building.
}
// We can probably use [aec.EmptyBuilder] for managing the output, but
// currently we're doing it all manually, so defining some consts for
// the basics we use.
@ -164,7 +116,7 @@ func cursorDown(out io.Writer, l uint) {
// Display prints the JSONMessage to out. If isTerminal is true, it erases
// the entire current line when displaying the progressbar. It returns an
// error if the [JSONMessage.Error] field is non-nil.
func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
func Display(jm jsonstream.Message, out io.Writer, isTerminal bool, width uint16) error {
if jm.Error != nil {
return jm.Error
}
@ -173,14 +125,17 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
clearLine(out)
endl = "\r"
_, _ = fmt.Fprint(out, endl)
} else if jm.Progress != nil && jm.Progress.String() != "" { // disable progressbar in non-terminal
} else if jm.Progress != nil && (jm.Progress.Current > 0 || jm.Progress.Total > 0) { // disable progressbar in non-terminal
return nil
}
if jm.ID != "" {
_, _ = fmt.Fprintf(out, "%s: ", jm.ID)
}
if jm.Progress != nil && isTerminal {
_, _ = fmt.Fprintf(out, "%s %s%s", jm.Status, jm.Progress.String(), endl)
if width == 0 {
width = 200
}
_, _ = fmt.Fprintf(out, "%s %s%s", jm.Status, RenderTUIProgress(*jm.Progress, width), endl)
} else if jm.Stream != "" {
_, _ = fmt.Fprintf(out, "%s%s", jm.Stream, endl)
} else {
@ -189,16 +144,16 @@ func (jm *JSONMessage) Display(out io.Writer, isTerminal bool) error {
return nil
}
type JSONMessagesStream iter.Seq2[JSONMessage, error]
type JSONMessagesStream iter.Seq2[jsonstream.Message, error]
// DisplayJSONMessagesStream reads a JSON message stream from in, and writes
// each [JSONMessage] to out.
// see DisplayJSONMessages for details
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error {
func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(jsonstream.Message)) error {
dec := json.NewDecoder(in)
var f JSONMessagesStream = func(yield func(JSONMessage, error) bool) {
var f JSONMessagesStream = func(yield func(jsonstream.Message, error) bool) {
for {
var jm JSONMessage
var jm jsonstream.Message
err := dec.Decode(&jm)
if errors.Is(err, io.EOF) {
break
@ -228,8 +183,15 @@ func DisplayJSONMessagesStream(in io.Reader, out io.Writer, terminalFd uintptr,
// - auxCallback allows handling the [JSONMessage.Aux] field. It is
// called if a JSONMessage contains an Aux field, in which case
// DisplayJSONMessagesStream does not present the JSONMessage.
func DisplayJSONMessages(messages JSONMessagesStream, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(JSONMessage)) error {
func DisplayJSONMessages(messages JSONMessagesStream, out io.Writer, terminalFd uintptr, isTerminal bool, auxCallback func(jsonstream.Message)) error {
ids := make(map[string]uint)
var width uint16 = 200
if isTerminal {
ws, err := term.GetWinsize(terminalFd)
if err == nil {
width = ws.Width
}
}
for jm, err := range messages {
var diff uint
@ -244,9 +206,6 @@ func DisplayJSONMessages(messages JSONMessagesStream, out io.Writer, terminalFd
continue
}
if jm.Progress != nil {
jm.Progress.terminalFd = terminalFd
}
if jm.ID != "" && jm.Progress != nil {
line, ok := ids[jm.ID]
if !ok {
@ -274,7 +233,7 @@ func DisplayJSONMessages(messages JSONMessagesStream, out io.Writer, terminalFd
// with multiple tags).
ids = make(map[string]uint)
}
err := jm.Display(out, isTerminal)
err := Display(jm, out, isTerminal, width)
if jm.ID != "" && isTerminal {
cursorDown(out, diff)
}

View File

@ -4,18 +4,78 @@ import (
"context"
"encoding/json"
"github.com/moby/moby/api/types"
"github.com/moby/moby/api/types/system"
)
// ServerVersion returns information of the docker client and server host.
func (cli *Client) ServerVersion(ctx context.Context) (types.Version, error) {
// ServerVersionOptions specifies options for the server version request.
type ServerVersionOptions struct {
// Currently no options are supported.
}
// ServerVersionResult contains information about the Docker server host.
type ServerVersionResult struct {
// Platform is the platform (product name) the server is running on.
Platform PlatformInfo
// Version is the version of the daemon.
Version string
// APIVersion is the highest API version supported by the server.
APIVersion string
// MinAPIVersion is the minimum API version the server supports.
MinAPIVersion string
// Os is the operating system the server runs on.
Os string
// Arch is the hardware architecture the server runs on.
Arch string
// Experimental indicates that the daemon runs with experimental
// features enabled.
//
// Deprecated: this field will be removed in the next version.
Experimental bool
// Components contains version information for the components making
// up the server. Information in this field is for informational
// purposes, and not part of the API contract.
Components []system.ComponentVersion
}
// PlatformInfo holds information about the platform (product name) the
// server is running on.
type PlatformInfo struct {
// Name is the name of the platform (for example, "Docker Engine - Community",
// or "Docker Desktop 4.49.0 (208003)")
Name string
}
// ServerVersion returns information of the Docker server host.
func (cli *Client) ServerVersion(ctx context.Context, _ ServerVersionOptions) (ServerVersionResult, error) {
resp, err := cli.get(ctx, "/version", nil, nil)
defer ensureReaderClosed(resp)
if err != nil {
return types.Version{}, err
return ServerVersionResult{}, err
}
var server types.Version
err = json.NewDecoder(resp.Body).Decode(&server)
return server, err
var v system.VersionResponse
err = json.NewDecoder(resp.Body).Decode(&v)
if err != nil {
return ServerVersionResult{}, err
}
return ServerVersionResult{
Platform: PlatformInfo{
Name: v.Platform.Name,
},
Version: v.Version,
APIVersion: v.APIVersion,
MinAPIVersion: v.MinAPIVersion,
Os: v.Os,
Arch: v.Arch,
Experimental: v.Experimental, //nolint:staticcheck // ignore deprecated field.
Components: v.Components,
}, nil
}

4
vendor/modules.txt vendored
View File

@ -168,7 +168,7 @@ github.com/moby/docker-image-spec/specs-go/v1
github.com/moby/go-archive
github.com/moby/go-archive/compression
github.com/moby/go-archive/tarheader
# github.com/moby/moby/api v1.52.0-beta.2.0.20251029225139-7a97e1cb401f
# github.com/moby/moby/api v1.52.0-beta.3.0.20251031021517-d96f50518f8d
## explicit; go 1.23.0
github.com/moby/moby/api/pkg/authconfig
github.com/moby/moby/api/pkg/stdcopy
@ -190,7 +190,7 @@ github.com/moby/moby/api/types/storage
github.com/moby/moby/api/types/swarm
github.com/moby/moby/api/types/system
github.com/moby/moby/api/types/volume
# github.com/moby/moby/client v0.1.0-beta.2.0.20251029225139-7a97e1cb401f
# github.com/moby/moby/client v0.1.0-beta.2.0.20251031021517-d96f50518f8d
## explicit; go 1.23.0
github.com/moby/moby/client
github.com/moby/moby/client/internal