e6907243af
We try to perform API-version negotiation as lazy as possible (and only execute when we are about to make an API request). However, some code requires API-version dependent handling (to set options, or remove options based on the version of the API we're using). Currently this code depended on the caller code to perform API negotiation (or to configure the API version) first, which may not happen, and because of that we may be missing options (or set options that are not supported on older API versions). This patch: - splits the code that triggered API-version negotiation to a separate Client.checkVersion() function. - updates NewVersionError to accept a context - updates NewVersionError to perform API-version negotiation (if enabled) - updates various Client functions to manually trigger API-version negotiation Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
73 lines
2.6 KiB
Go
73 lines
2.6 KiB
Go
package client // import "github.com/docker/docker/client"
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/versions"
|
|
)
|
|
|
|
// ContainerExecCreate creates a new exec configuration to run an exec process.
|
|
func (cli *Client) ContainerExecCreate(ctx context.Context, container string, config types.ExecConfig) (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.
|
|
//
|
|
// Normally, version-negotiation (if enabled) would not happen until
|
|
// the API request is made.
|
|
cli.checkVersion(ctx)
|
|
|
|
if err := cli.NewVersionError(ctx, "1.25", "env"); len(config.Env) != 0 && err != nil {
|
|
return response, err
|
|
}
|
|
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
|
config.ConsoleSize = nil
|
|
}
|
|
|
|
resp, err := cli.post(ctx, "/containers/"+container+"/exec", nil, config, nil)
|
|
defer ensureReaderClosed(resp)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
err = json.NewDecoder(resp.body).Decode(&response)
|
|
return response, err
|
|
}
|
|
|
|
// ContainerExecStart starts an exec process already created in the docker host.
|
|
func (cli *Client) ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error {
|
|
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
|
config.ConsoleSize = nil
|
|
}
|
|
resp, err := cli.post(ctx, "/exec/"+execID+"/start", nil, config, nil)
|
|
ensureReaderClosed(resp)
|
|
return err
|
|
}
|
|
|
|
// ContainerExecAttach attaches a connection to an exec process in the server.
|
|
// It returns a types.HijackedConnection with the hijacked connection
|
|
// and the a reader to get output. It's up to the called to close
|
|
// the hijacked connection by calling types.HijackedResponse.Close.
|
|
func (cli *Client) ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error) {
|
|
if versions.LessThan(cli.ClientVersion(), "1.42") {
|
|
config.ConsoleSize = nil
|
|
}
|
|
return cli.postHijacked(ctx, "/exec/"+execID+"/start", nil, config, http.Header{
|
|
"Content-Type": {"application/json"},
|
|
})
|
|
}
|
|
|
|
// ContainerExecInspect returns information about a specific exec process on the docker host.
|
|
func (cli *Client) ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error) {
|
|
var response types.ContainerExecInspect
|
|
resp, err := cli.get(ctx, "/exec/"+execID+"/json", nil, nil)
|
|
if err != nil {
|
|
return response, err
|
|
}
|
|
|
|
err = json.NewDecoder(resp.body).Decode(&response)
|
|
ensureReaderClosed(resp)
|
|
return response, err
|
|
}
|