mirror of
https://github.com/docker/cli.git
synced 2026-09-27 01:40:31 -04:00
vendor: github.com/moby/moby/client v0.5.2-dev (b9b109e4d341)
full diff: https://github.com/moby/moby/compare/client/v0.5.1...b9b109e4d341 Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ require (
|
||||
github.com/mattn/go-runewidth v0.0.28
|
||||
github.com/moby/go-archive v0.3.3
|
||||
github.com/moby/moby/api v1.55.1-0.20260903164743-b9b109e4d341
|
||||
github.com/moby/moby/client v0.5.1
|
||||
github.com/moby/moby/client v0.5.2-0.20260903164743-b9b109e4d341
|
||||
github.com/moby/patternmatcher v0.6.1
|
||||
github.com/moby/swarmkit/v2 v2.1.2
|
||||
github.com/moby/sys/atomicwriter v0.1.0
|
||||
|
||||
+2
-2
@@ -90,8 +90,8 @@ github.com/moby/go-archive v0.3.3 h1:OxxR9paxsluYi+zDUEXTTaIxtkK3viymW+Ka7vRhhME
|
||||
github.com/moby/go-archive v0.3.3/go.mod h1:Npdv43fFqlhZW7Xo8fbm3ZMYFvAGNviUPqX21VERbcE=
|
||||
github.com/moby/moby/api v1.55.1-0.20260903164743-b9b109e4d341 h1:ooFZgSrQ/xRDfGves7imF3goa+32bEcJrcXIDlL/qpI=
|
||||
github.com/moby/moby/api v1.55.1-0.20260903164743-b9b109e4d341/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
|
||||
github.com/moby/moby/client v0.5.1 h1:tYNaJno4c0HXz12y5BiqEDy0rVTYkWzI26lGvnTMiJw=
|
||||
github.com/moby/moby/client v0.5.1/go.mod h1:odLstlZ6uSnfvAgVxMpvgmb8SUdd+siH2T0GBuxVAlM=
|
||||
github.com/moby/moby/client v0.5.2-0.20260903164743-b9b109e4d341 h1:/XUuyJxH/HXe5MBcQo+YG9hAtZTQNpWFeJ5PcxL+hs8=
|
||||
github.com/moby/moby/client v0.5.2-0.20260903164743-b9b109e4d341/go.mod h1:odLstlZ6uSnfvAgVxMpvgmb8SUdd+siH2T0GBuxVAlM=
|
||||
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
|
||||
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/swarmkit/v2 v2.1.2 h1:1WDZAI6HVYNKdCG4zlXnTAPyLsLwuhRGWlHoOUf5Z6I=
|
||||
|
||||
+2
-4
@@ -24,13 +24,11 @@ func (cli *Client) CheckpointCreate(ctx context.Context, containerID string, opt
|
||||
if err != nil {
|
||||
return CheckpointCreateResult{}, err
|
||||
}
|
||||
requestBody := checkpoint.CreateRequest{
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/checkpoints", nil, nil, checkpoint.CreateRequest{
|
||||
CheckpointID: options.CheckpointID,
|
||||
CheckpointDir: options.CheckpointDir,
|
||||
Exit: options.Exit,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/checkpoints", nil, requestBody, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
return CheckpointCreateResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ const DummyHost = "api.moby.localhost"
|
||||
// overriding the version and disable API-version negotiation.
|
||||
//
|
||||
// This version may be lower than the version of the api library module used.
|
||||
const MaxAPIVersion = "1.55"
|
||||
const MaxAPIVersion = "1.56"
|
||||
|
||||
// MinAPIVersion is the minimum API version supported by the client. API versions
|
||||
// below this version are not considered when performing API-version negotiation.
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ type ConfigCreateResult struct {
|
||||
|
||||
// ConfigCreate creates a new config.
|
||||
func (cli *Client) ConfigCreate(ctx context.Context, options ConfigCreateOptions) (ConfigCreateResult, error) {
|
||||
resp, err := cli.post(ctx, "/configs/create", nil, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/configs/create", nil, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ConfigCreateResult{}, err
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ func (cli *Client) ConfigUpdate(ctx context.Context, id string, options ConfigUp
|
||||
}
|
||||
query := url.Values{}
|
||||
query.Set("version", options.Version.String())
|
||||
resp, err := cli.post(ctx, "/configs/"+id+"/update", query, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/configs/"+id+"/update", query, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ConfigUpdateResult{}, err
|
||||
|
||||
+1
-1
@@ -65,7 +65,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti
|
||||
}
|
||||
|
||||
var response container.CommitResponse
|
||||
resp, err := cli.post(ctx, "/commit", query, options.Config, nil)
|
||||
resp, err := cli.post(ctx, "/commit", query, nil, options.Config)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ContainerCommitResult{}, err
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ func (cli *Client) CopyToContainer(ctx context.Context, containerID string, opti
|
||||
query.Set("copyUIDGID", "true")
|
||||
}
|
||||
|
||||
response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, options.Content, nil)
|
||||
response, err := cli.putRaw(ctx, "/containers/"+containerID+"/archive", query, nil, options.Content)
|
||||
defer ensureReaderClosed(response)
|
||||
if err != nil {
|
||||
return CopyToContainerResult{}, err
|
||||
|
||||
+30
-37
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
@@ -35,13 +35,6 @@ func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateO
|
||||
return ContainerCreateResult{}, cerrdefs.ErrInvalidArgument.WithMessage("config.Image or Image is required")
|
||||
}
|
||||
|
||||
var response container.CreateResponse
|
||||
|
||||
if options.HostConfig != nil {
|
||||
options.HostConfig.CapAdd = normalizeCapabilities(options.HostConfig.CapAdd)
|
||||
options.HostConfig.CapDrop = normalizeCapabilities(options.HostConfig.CapDrop)
|
||||
}
|
||||
|
||||
query := url.Values{}
|
||||
if options.Platform != nil {
|
||||
if p := formatPlatform(*options.Platform); p != "unknown" {
|
||||
@@ -53,18 +46,17 @@ func (cli *Client) ContainerCreate(ctx context.Context, options ContainerCreateO
|
||||
query.Set("name", options.Name)
|
||||
}
|
||||
|
||||
body := container.CreateRequest{
|
||||
resp, err := cli.post(ctx, "/containers/create", query, nil, container.CreateRequest{
|
||||
Config: cfg,
|
||||
HostConfig: options.HostConfig,
|
||||
HostConfig: normalizeHostConfig(options.HostConfig),
|
||||
NetworkingConfig: options.NetworkingConfig,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/create", query, body, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ContainerCreateResult{}, err
|
||||
}
|
||||
|
||||
var response container.CreateResponse
|
||||
err = json.NewDecoder(resp.Body).Decode(&response)
|
||||
return ContainerCreateResult{ID: response.ID, Warnings: response.Warnings}, err
|
||||
}
|
||||
@@ -86,6 +78,17 @@ func formatPlatform(platform ocispec.Platform) string {
|
||||
// allCapabilities is a magic value for "all capabilities"
|
||||
const allCapabilities = "ALL"
|
||||
|
||||
// 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(c string) string {
|
||||
c = strings.ToUpper(c)
|
||||
if c != allCapabilities && !strings.HasPrefix(c, "CAP_") {
|
||||
c = "CAP_" + c
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// normalizeCapabilities normalizes capabilities to their canonical form,
|
||||
// removes duplicates, and sorts the results.
|
||||
//
|
||||
@@ -94,32 +97,22 @@ const allCapabilities = "ALL"
|
||||
//
|
||||
// [caps.NormalizeLegacyCapabilities]: https://github.com/moby/moby/blob/v28.3.2/oci/caps/utils.go#L56
|
||||
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)
|
||||
normalized := slices.Clone(caps)
|
||||
for i, c := range normalized {
|
||||
normalized[i] = normalizeCap(c)
|
||||
}
|
||||
|
||||
sort.Strings(normalized)
|
||||
return normalized
|
||||
slices.Sort(normalized)
|
||||
return slices.Compact(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(capability string) string {
|
||||
capability = strings.ToUpper(capability)
|
||||
if capability == allCapabilities {
|
||||
return capability
|
||||
// normalizeHostConfig returns a shallow copy of hostConfig with capabilities normalized.
|
||||
func normalizeHostConfig(hostConfig *container.HostConfig) *container.HostConfig {
|
||||
if hostConfig == nil {
|
||||
return nil
|
||||
}
|
||||
if !strings.HasPrefix(capability, "CAP_") {
|
||||
capability = "CAP_" + capability
|
||||
}
|
||||
return capability
|
||||
|
||||
normalized := *hostConfig
|
||||
normalized.CapAdd = normalizeCapabilities(hostConfig.CapAdd)
|
||||
normalized.CapDrop = normalizeCapabilities(hostConfig.CapDrop)
|
||||
return &normalized
|
||||
}
|
||||
|
||||
+4
-7
@@ -42,7 +42,7 @@ func (cli *Client) ExecCreate(ctx context.Context, containerID string, options E
|
||||
return ExecCreateResult{}, err
|
||||
}
|
||||
|
||||
req := container.ExecCreateRequest{
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, nil, container.ExecCreateRequest{
|
||||
User: options.User,
|
||||
Privileged: options.Privileged,
|
||||
Tty: options.TTY,
|
||||
@@ -54,9 +54,7 @@ func (cli *Client) ExecCreate(ctx context.Context, containerID string, options E
|
||||
Env: options.Env,
|
||||
WorkingDir: options.WorkingDir,
|
||||
Cmd: options.Cmd,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/exec", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ExecCreateResult{}, err
|
||||
@@ -91,12 +89,11 @@ func (cli *Client) ExecStart(ctx context.Context, execID string, options ExecSta
|
||||
return ExecStartResult{}, err
|
||||
}
|
||||
|
||||
req := container.ExecStartRequest{
|
||||
resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, nil, container.ExecStartRequest{
|
||||
Detach: options.Detach,
|
||||
Tty: options.TTY,
|
||||
ConsoleSize: consoleSize,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
return ExecStartResult{}, err
|
||||
}
|
||||
|
||||
+4
-9
@@ -26,15 +26,10 @@ func (cli *Client) ContainerUpdate(ctx context.Context, containerID string, opti
|
||||
return ContainerUpdateResult{}, err
|
||||
}
|
||||
|
||||
updateConfig := container.UpdateConfig{}
|
||||
if options.Resources != nil {
|
||||
updateConfig.Resources = *options.Resources
|
||||
}
|
||||
if options.RestartPolicy != nil {
|
||||
updateConfig.RestartPolicy = *options.RestartPolicy
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, updateConfig, nil)
|
||||
resp, err := cli.post(ctx, "/containers/"+containerID+"/update", nil, nil, container.UpdateConfig{
|
||||
Resources: valueOrZero(options.Resources),
|
||||
RestartPolicy: valueOrZero(options.RestartPolicy),
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ContainerUpdateResult{}, err
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu
|
||||
if err != nil {
|
||||
return HijackedResponse{}, err
|
||||
}
|
||||
req, err := cli.buildRequest(ctx, http.MethodPost, cli.getAPIPath(ctx, path, query), jsonBody, headers)
|
||||
req, err := cli.buildRequest(ctx, http.MethodPost, cli.getAPIPath(ctx, path, query), headers, jsonBody)
|
||||
if err != nil {
|
||||
return HijackedResponse{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
|
||||
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
||||
headers.Set("Content-Type", "application/x-tar")
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
||||
resp, err := cli.postRaw(ctx, "/build", query, headers, buildContext)
|
||||
if err != nil {
|
||||
return ImageBuildResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ func (cli *Client) ImageImport(ctx context.Context, source ImageImportSource, re
|
||||
query.Add("changes", change)
|
||||
}
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/images/create", query, source.Source, nil)
|
||||
resp, err := cli.postRaw(ctx, "/images/create", query, nil, source.Source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+2
-3
@@ -42,9 +42,8 @@ func (cli *Client) ImageLoad(ctx context.Context, input io.Reader, loadOpts ...I
|
||||
query["platform"] = p
|
||||
}
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/images/load", query, input, http.Header{
|
||||
"Content-Type": {"application/x-tar"},
|
||||
})
|
||||
headers := http.Header{"Content-Type": {"application/x-tar"}}
|
||||
resp, err := cli.postRaw(ctx, "/images/load", query, headers, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -89,5 +89,5 @@ func (cli *Client) tryImageCreate(ctx context.Context, query url.Values, resolve
|
||||
hdr.Set(registry.AuthHeader, registryAuth)
|
||||
}
|
||||
}
|
||||
return cli.post(ctx, "/images/create", query, nil, hdr)
|
||||
return cli.post(ctx, "/images/create", query, hdr, nil)
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,5 +94,5 @@ func (cli *Client) tryImagePush(ctx context.Context, imageID string, query url.V
|
||||
// We use [http.NoBody], which gets marshaled to an empty JSON document.
|
||||
//
|
||||
// see: https://github.com/moby/moby/commit/ea29dffaa541289591aa44fa85d2a596ce860e16
|
||||
return cli.post(ctx, "/images/"+imageID+"/push", query, http.NoBody, hdr)
|
||||
return cli.post(ctx, "/images/"+imageID+"/push", query, hdr, http.NoBody)
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ func (cli *Client) RegistryLogin(ctx context.Context, options RegistryLoginOptio
|
||||
RegistryToken: options.RegistryToken,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/auth", url.Values{}, auth, nil)
|
||||
resp, err := cli.post(ctx, "/auth", url.Values{}, nil, auth)
|
||||
defer ensureReaderClosed(resp)
|
||||
|
||||
if err != nil {
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ func (cli *Client) NetworkConnect(ctx context.Context, networkID string, options
|
||||
Container: containerID,
|
||||
EndpointConfig: options.EndpointConfig,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nc, nil)
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/connect", nil, nil, nc)
|
||||
defer ensureReaderClosed(resp)
|
||||
return NetworkConnectResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ func (cli *Client) NetworkCreate(ctx context.Context, name string, options Netwo
|
||||
req.ConfigFrom = &network.ConfigReference{Network: options.ConfigFrom}
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/networks/create", nil, req, nil)
|
||||
resp, err := cli.post(ctx, "/networks/create", nil, nil, req)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return NetworkCreateResult{}, err
|
||||
|
||||
+2
-3
@@ -30,11 +30,10 @@ func (cli *Client) NetworkDisconnect(ctx context.Context, networkID string, opti
|
||||
return NetworkDisconnectResult{}, err
|
||||
}
|
||||
|
||||
req := network.DisconnectRequest{
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, nil, network.DisconnectRequest{
|
||||
Container: containerID,
|
||||
Force: options.Force,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/networks/"+networkID+"/disconnect", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
return NetworkDisconnectResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ func (cli *Client) NodeUpdate(ctx context.Context, nodeID string, options NodeUp
|
||||
|
||||
query := url.Values{}
|
||||
query.Set("version", options.Version.String())
|
||||
resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/nodes/"+nodeID+"/update", query, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
return NodeUpdateResult{}, err
|
||||
}
|
||||
|
||||
+33
-7
@@ -26,7 +26,8 @@ const RFC3339NanoFixed = "2006-01-02T15:04:05.000000000Z07:00"
|
||||
type DisplayOpt func(*displayOpts) error
|
||||
|
||||
type displayOpts struct {
|
||||
auxCallback func(jsonstream.Message)
|
||||
auxCallback func(jsonstream.Message)
|
||||
messagePrinter func(jsonstream.Message, io.Writer) error
|
||||
}
|
||||
|
||||
// WithAuxCallback registers a callback that is invoked for auxiliary
|
||||
@@ -39,6 +40,18 @@ func WithAuxCallback(fn func(jsonstream.Message)) DisplayOpt {
|
||||
}
|
||||
}
|
||||
|
||||
// WithMessagePrinter sets a custom printer for non-auxiliary messages.
|
||||
// If set, [DisplayStream] and [DisplayMessages] pass each message to fn instead
|
||||
// of using the default terminal-aware presentation. The caller is responsible
|
||||
// for handling errors reported through [jsonstream.Message.Error] and any
|
||||
// terminal handling, including progress rendering and terminal-width detection.
|
||||
func WithMessagePrinter(fn func(jsonstream.Message, io.Writer) error) DisplayOpt {
|
||||
return func(opts *displayOpts) error {
|
||||
opts.messagePrinter = fn
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func RenderTUIProgress(p jsonstream.Progress, width uint16) string {
|
||||
var (
|
||||
pbBox string
|
||||
@@ -232,13 +245,19 @@ func displayJSONMessages(messages iter.Seq2[jsonstream.Message, error], out io.W
|
||||
}
|
||||
}
|
||||
auxCallback := cfg.auxCallback
|
||||
messagePrinter := cfg.messagePrinter
|
||||
|
||||
ids := make(map[string]uint)
|
||||
var width uint16 = 200
|
||||
if isTerminal {
|
||||
ws, err := term.GetWinsize(terminalFd)
|
||||
if err == nil {
|
||||
width = ws.Width
|
||||
var (
|
||||
ids map[string]uint
|
||||
width uint16 = 200
|
||||
)
|
||||
if messagePrinter == nil {
|
||||
ids = make(map[string]uint)
|
||||
if isTerminal {
|
||||
ws, err := term.GetWinsize(terminalFd)
|
||||
if err == nil {
|
||||
width = ws.Width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +274,13 @@ func displayJSONMessages(messages iter.Seq2[jsonstream.Message, error], out io.W
|
||||
continue
|
||||
}
|
||||
|
||||
if messagePrinter != nil {
|
||||
if err := messagePrinter(jm, out); err != nil {
|
||||
return err
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if jm.ID != "" && jm.Progress != nil {
|
||||
line, ok := ids[jm.ID]
|
||||
if !ok {
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ func (cli *Client) PluginCreate(ctx context.Context, createContext io.Reader, cr
|
||||
query := url.Values{}
|
||||
query.Set("name", createOptions.RepoName)
|
||||
|
||||
resp, err := cli.postRaw(ctx, "/plugins/create", query, createContext, headers)
|
||||
resp, err := cli.postRaw(ctx, "/plugins/create", query, headers, createContext)
|
||||
defer ensureReaderClosed(resp)
|
||||
return PluginCreateResult{}, err
|
||||
}
|
||||
|
||||
+5
-6
@@ -99,13 +99,12 @@ func (cli *Client) tryPluginPrivileges(ctx context.Context, query url.Values, re
|
||||
})
|
||||
}
|
||||
|
||||
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges plugin.Privileges, registryAuth string) (*http.Response, error) {
|
||||
return cli.post(ctx, "/plugins/pull", query, privileges, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
func (cli *Client) tryPluginPull(ctx context.Context, query url.Values, privileges []plugin.Privilege, registryAuth string) (*http.Response, error) {
|
||||
headers := http.Header{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/plugins/pull", query, headers, privileges)
|
||||
}
|
||||
|
||||
func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options pluginOptions) (plugin.Privileges, error) {
|
||||
func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values, options pluginOptions) ([]plugin.Privilege, error) {
|
||||
resp, err := cli.tryPluginPrivileges(ctx, query, options.getRegistryAuth())
|
||||
if cerrdefs.IsUnauthorized(err) && options.getPrivilegeFunc() != nil {
|
||||
// TODO: do inspect before to check existing name before checking privileges
|
||||
@@ -122,7 +121,7 @@ func (cli *Client) checkPluginPermissions(ctx context.Context, query url.Values,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var privileges plugin.Privileges
|
||||
var privileges []plugin.Privilege
|
||||
if err := json.NewDecoder(resp.Body).Decode(&privileges); err != nil {
|
||||
ensureReaderClosed(resp)
|
||||
return nil, err
|
||||
|
||||
+2
-3
@@ -24,9 +24,8 @@ func (cli *Client) PluginPush(ctx context.Context, name string, options PluginPu
|
||||
if err != nil {
|
||||
return PluginPushResult{}, err
|
||||
}
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, nil, http.Header{
|
||||
registry.AuthHeader: {options.RegistryAuth},
|
||||
})
|
||||
headers := http.Header{registry.AuthHeader: {options.RegistryAuth}}
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/push", nil, headers, nil)
|
||||
if err != nil {
|
||||
return PluginPushResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ func (cli *Client) PluginSet(ctx context.Context, name string, options PluginSet
|
||||
return PluginSetResult{}, err
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, options.Args, nil)
|
||||
resp, err := cli.post(ctx, "/plugins/"+name+"/set", nil, nil, options.Args)
|
||||
defer ensureReaderClosed(resp)
|
||||
return PluginSetResult{}, err
|
||||
}
|
||||
|
||||
+3
-4
@@ -58,10 +58,9 @@ func (cli *Client) PluginUpgrade(ctx context.Context, name string, options Plugi
|
||||
return resp.Body, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges plugin.Privileges, name, registryAuth string) (*http.Response, error) {
|
||||
return cli.post(ctx, "/plugins/"+name+"/upgrade", query, privileges, http.Header{
|
||||
registry.AuthHeader: {registryAuth},
|
||||
})
|
||||
func (cli *Client) tryPluginUpgrade(ctx context.Context, query url.Values, privileges []plugin.Privilege, name, registryAuth string) (*http.Response, error) {
|
||||
headers := http.Header{registry.AuthHeader: {registryAuth}}
|
||||
return cli.post(ctx, "/plugins/"+name+"/upgrade", query, headers, privileges)
|
||||
}
|
||||
|
||||
func (o *PluginUpgradeOptions) getRegistryAuth() string {
|
||||
|
||||
+14
-14
@@ -19,49 +19,49 @@ import (
|
||||
|
||||
// head sends an http request to the docker API using the method HEAD.
|
||||
func (cli *Client) head(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) {
|
||||
return cli.sendRequest(ctx, http.MethodHead, path, query, nil, headers)
|
||||
return cli.sendRequest(ctx, http.MethodHead, path, query, headers, nil)
|
||||
}
|
||||
|
||||
// get sends an http request to the docker API using the method GET with a specific Go context.
|
||||
func (cli *Client) get(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) {
|
||||
return cli.sendRequest(ctx, http.MethodGet, path, query, nil, headers)
|
||||
return cli.sendRequest(ctx, http.MethodGet, path, query, headers, nil)
|
||||
}
|
||||
|
||||
// post sends an http POST request to the API.
|
||||
func (cli *Client) post(ctx context.Context, path string, query url.Values, body any, headers http.Header) (*http.Response, error) {
|
||||
func (cli *Client) post(ctx context.Context, path string, query url.Values, headers http.Header, body any) (*http.Response, error) {
|
||||
jsonBody, headers, err := prepareJSONRequest(body, headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cli.sendRequest(ctx, http.MethodPost, path, query, jsonBody, headers)
|
||||
return cli.sendRequest(ctx, http.MethodPost, path, query, headers, jsonBody)
|
||||
}
|
||||
|
||||
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) {
|
||||
return cli.sendRequest(ctx, http.MethodPost, path, query, body, headers)
|
||||
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, headers http.Header, body io.Reader) (*http.Response, error) {
|
||||
return cli.sendRequest(ctx, http.MethodPost, path, query, headers, body)
|
||||
}
|
||||
|
||||
func (cli *Client) put(ctx context.Context, path string, query url.Values, body any, headers http.Header) (*http.Response, error) {
|
||||
func (cli *Client) put(ctx context.Context, path string, query url.Values, headers http.Header, body any) (*http.Response, error) {
|
||||
jsonBody, headers, err := prepareJSONRequest(body, headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cli.putRaw(ctx, path, query, jsonBody, headers)
|
||||
return cli.putRaw(ctx, path, query, headers, jsonBody)
|
||||
}
|
||||
|
||||
// putRaw sends an http request to the docker API using the method PUT.
|
||||
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) {
|
||||
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, headers http.Header, body io.Reader) (*http.Response, error) {
|
||||
// PUT requests are expected to always have a body (apparently)
|
||||
// so explicitly pass an empty body to sendRequest to signal that
|
||||
// it should set the Content-Type header if not already present.
|
||||
if body == nil {
|
||||
body = http.NoBody
|
||||
}
|
||||
return cli.sendRequest(ctx, http.MethodPut, path, query, body, headers)
|
||||
return cli.sendRequest(ctx, http.MethodPut, path, query, headers, body)
|
||||
}
|
||||
|
||||
// delete sends an http request to the docker API using the method DELETE.
|
||||
func (cli *Client) delete(ctx context.Context, path string, query url.Values, headers http.Header) (*http.Response, error) {
|
||||
return cli.sendRequest(ctx, http.MethodDelete, path, query, nil, headers)
|
||||
return cli.sendRequest(ctx, http.MethodDelete, path, query, headers, nil)
|
||||
}
|
||||
|
||||
// prepareJSONRequest encodes the given body to JSON and returns it as an [io.Reader], and sets the Content-Type
|
||||
@@ -87,7 +87,7 @@ func prepareJSONRequest(body any, headers http.Header) (io.Reader, http.Header,
|
||||
return jsonBody, hdr, nil
|
||||
}
|
||||
|
||||
func (cli *Client) buildRequest(ctx context.Context, method, path string, body io.Reader, headers http.Header) (*http.Request, error) {
|
||||
func (cli *Client) buildRequest(ctx context.Context, method, path string, headers http.Header, body io.Reader) (*http.Request, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, method, path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -104,8 +104,8 @@ func (cli *Client) buildRequest(ctx context.Context, method, path string, body i
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers http.Header) (*http.Response, error) {
|
||||
req, err := cli.buildRequest(ctx, method, cli.getAPIPath(ctx, path, query), body, headers)
|
||||
func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, headers http.Header, body io.Reader) (*http.Response, error) {
|
||||
req, err := cli.buildRequest(ctx, method, cli.getAPIPath(ctx, path, query), headers, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ type SecretCreateResult struct {
|
||||
|
||||
// SecretCreate creates a new secret.
|
||||
func (cli *Client) SecretCreate(ctx context.Context, options SecretCreateOptions) (SecretCreateResult, error) {
|
||||
resp, err := cli.post(ctx, "/secrets/create", nil, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/secrets/create", nil, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return SecretCreateResult{}, err
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ func (cli *Client) SecretUpdate(ctx context.Context, id string, options SecretUp
|
||||
}
|
||||
query := url.Values{}
|
||||
query.Set("version", options.Version.String())
|
||||
resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/secrets/"+id+"/update", query, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return SecretUpdateResult{}, err
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ func (cli *Client) ServiceCreate(ctx context.Context, options ServiceCreateOptio
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers[registry.AuthHeader] = []string{options.EncodedRegistryAuth}
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/create", nil, options.Spec, headers)
|
||||
resp, err := cli.post(ctx, "/services/create", nil, headers, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ServiceCreateResult{}, err
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, options
|
||||
if options.EncodedRegistryAuth != "" {
|
||||
headers.Set(registry.AuthHeader, options.EncodedRegistryAuth)
|
||||
}
|
||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, options.Spec, headers)
|
||||
resp, err := cli.post(ctx, "/services/"+serviceID+"/update", query, headers, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return ServiceUpdateResult{}, err
|
||||
|
||||
+2
-4
@@ -29,7 +29,7 @@ type SwarmInitResult struct {
|
||||
|
||||
// SwarmInit initializes the swarm.
|
||||
func (cli *Client) SwarmInit(ctx context.Context, options SwarmInitOptions) (SwarmInitResult, error) {
|
||||
req := swarm.InitRequest{
|
||||
resp, err := cli.post(ctx, "/swarm/init", nil, nil, swarm.InitRequest{
|
||||
ListenAddr: options.ListenAddr,
|
||||
AdvertiseAddr: options.AdvertiseAddr,
|
||||
DataPathAddr: options.DataPathAddr,
|
||||
@@ -40,9 +40,7 @@ func (cli *Client) SwarmInit(ctx context.Context, options SwarmInitOptions) (Swa
|
||||
Availability: options.Availability,
|
||||
DefaultAddrPool: options.DefaultAddrPool,
|
||||
SubnetSize: options.SubnetSize,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/swarm/init", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return SwarmInitResult{}, err
|
||||
|
||||
+2
-4
@@ -23,16 +23,14 @@ type SwarmJoinResult struct {
|
||||
|
||||
// SwarmJoin joins the swarm.
|
||||
func (cli *Client) SwarmJoin(ctx context.Context, options SwarmJoinOptions) (SwarmJoinResult, error) {
|
||||
req := swarm.JoinRequest{
|
||||
resp, err := cli.post(ctx, "/swarm/join", nil, nil, swarm.JoinRequest{
|
||||
ListenAddr: options.ListenAddr,
|
||||
AdvertiseAddr: options.AdvertiseAddr,
|
||||
DataPathAddr: options.DataPathAddr,
|
||||
RemoteAddrs: options.RemoteAddrs,
|
||||
JoinToken: options.JoinToken,
|
||||
Availability: options.Availability,
|
||||
}
|
||||
|
||||
resp, err := cli.post(ctx, "/swarm/join", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
return SwarmJoinResult{}, err
|
||||
}
|
||||
|
||||
+2
-3
@@ -16,10 +16,9 @@ type SwarmUnlockResult struct{}
|
||||
|
||||
// SwarmUnlock unlocks locked swarm.
|
||||
func (cli *Client) SwarmUnlock(ctx context.Context, options SwarmUnlockOptions) (SwarmUnlockResult, error) {
|
||||
req := &swarm.UnlockRequest{
|
||||
resp, err := cli.post(ctx, "/swarm/unlock", nil, nil, swarm.UnlockRequest{
|
||||
UnlockKey: options.Key,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/swarm/unlock", nil, req, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
return SwarmUnlockResult{}, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ func (cli *Client) SwarmUpdate(ctx context.Context, options SwarmUpdateOptions)
|
||||
query.Set("rotateWorkerToken", strconv.FormatBool(options.RotateWorkerToken))
|
||||
query.Set("rotateManagerToken", strconv.FormatBool(options.RotateManagerToken))
|
||||
query.Set("rotateManagerUnlockKey", strconv.FormatBool(options.RotateManagerUnlockKey))
|
||||
resp, err := cli.post(ctx, "/swarm/update", query, options.Spec, nil)
|
||||
resp, err := cli.post(ctx, "/swarm/update", query, nil, options.Spec)
|
||||
defer ensureReaderClosed(resp)
|
||||
return SwarmUpdateResult{}, err
|
||||
}
|
||||
|
||||
+8
@@ -33,6 +33,14 @@ func trimID(objType, id string) (string, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// valueOrZero returns the value pointed to by p, or the zero value of T if p is nil.
|
||||
func valueOrZero[T any](p *T) (zero T) {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return zero
|
||||
}
|
||||
|
||||
// parseAPIVersion checks v to be a well-formed ("<major>.<minor>")
|
||||
// API version. It returns an error if the value is empty or does not
|
||||
// have the correct format, but does not validate if the API version is
|
||||
|
||||
+2
-3
@@ -23,14 +23,13 @@ type VolumeCreateResult struct {
|
||||
|
||||
// VolumeCreate creates a volume in the docker host.
|
||||
func (cli *Client) VolumeCreate(ctx context.Context, options VolumeCreateOptions) (VolumeCreateResult, error) {
|
||||
createRequest := volume.CreateRequest{
|
||||
resp, err := cli.post(ctx, "/volumes/create", nil, nil, volume.CreateRequest{
|
||||
Name: options.Name,
|
||||
Driver: options.Driver,
|
||||
DriverOpts: options.DriverOpts,
|
||||
Labels: options.Labels,
|
||||
ClusterVolumeSpec: options.ClusterVolumeSpec,
|
||||
}
|
||||
resp, err := cli.post(ctx, "/volumes/create", nil, createRequest, nil)
|
||||
})
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return VolumeCreateResult{}, err
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ func (cli *Client) VolumeUpdate(ctx context.Context, volumeID string, options Vo
|
||||
query := url.Values{}
|
||||
query.Set("version", options.Version.String())
|
||||
|
||||
resp, err := cli.put(ctx, "/volumes/"+volumeID, query, options, nil)
|
||||
resp, err := cli.put(ctx, "/volumes/"+volumeID, query, nil, options)
|
||||
defer ensureReaderClosed(resp)
|
||||
if err != nil {
|
||||
return VolumeUpdateResult{}, err
|
||||
|
||||
Vendored
+1
-1
@@ -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.5.1
|
||||
# github.com/moby/moby/client v0.5.2-0.20260903164743-b9b109e4d341
|
||||
## explicit; go 1.24
|
||||
github.com/moby/moby/client
|
||||
github.com/moby/moby/client/internal
|
||||
|
||||
Reference in New Issue
Block a user