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>
144 lines
3.8 KiB
Go
144 lines
3.8 KiB
Go
package client // import "github.com/docker/docker/client"
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/container"
|
|
)
|
|
|
|
// ImageBuild sends a request to the daemon to build images.
|
|
// The Body in the response implements an io.ReadCloser and it's up to the caller to
|
|
// close it.
|
|
func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
|
query, err := cli.imageBuildOptionsToQuery(ctx, options)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
|
|
buf, err := json.Marshal(options.AuthConfigs)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
|
|
headers := http.Header{}
|
|
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
|
headers.Set("Content-Type", "application/x-tar")
|
|
|
|
serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
|
|
return types.ImageBuildResponse{
|
|
Body: serverResp.body,
|
|
OSType: getDockerOS(serverResp.header.Get("Server")),
|
|
}, nil
|
|
}
|
|
|
|
func (cli *Client) imageBuildOptionsToQuery(ctx context.Context, options types.ImageBuildOptions) (url.Values, error) {
|
|
query := url.Values{
|
|
"t": options.Tags,
|
|
"securityopt": options.SecurityOpt,
|
|
"extrahosts": options.ExtraHosts,
|
|
}
|
|
if options.SuppressOutput {
|
|
query.Set("q", "1")
|
|
}
|
|
if options.RemoteContext != "" {
|
|
query.Set("remote", options.RemoteContext)
|
|
}
|
|
if options.NoCache {
|
|
query.Set("nocache", "1")
|
|
}
|
|
if options.Remove {
|
|
query.Set("rm", "1")
|
|
} else {
|
|
query.Set("rm", "0")
|
|
}
|
|
|
|
if options.ForceRemove {
|
|
query.Set("forcerm", "1")
|
|
}
|
|
|
|
if options.PullParent {
|
|
query.Set("pull", "1")
|
|
}
|
|
|
|
if options.Squash {
|
|
if err := cli.NewVersionError(ctx, "1.25", "squash"); err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("squash", "1")
|
|
}
|
|
|
|
if !container.Isolation.IsDefault(options.Isolation) {
|
|
query.Set("isolation", string(options.Isolation))
|
|
}
|
|
|
|
query.Set("cpusetcpus", options.CPUSetCPUs)
|
|
query.Set("networkmode", options.NetworkMode)
|
|
query.Set("cpusetmems", options.CPUSetMems)
|
|
query.Set("cpushares", strconv.FormatInt(options.CPUShares, 10))
|
|
query.Set("cpuquota", strconv.FormatInt(options.CPUQuota, 10))
|
|
query.Set("cpuperiod", strconv.FormatInt(options.CPUPeriod, 10))
|
|
query.Set("memory", strconv.FormatInt(options.Memory, 10))
|
|
query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
|
|
query.Set("cgroupparent", options.CgroupParent)
|
|
query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
|
|
query.Set("dockerfile", options.Dockerfile)
|
|
query.Set("target", options.Target)
|
|
|
|
ulimitsJSON, err := json.Marshal(options.Ulimits)
|
|
if err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("ulimits", string(ulimitsJSON))
|
|
|
|
buildArgsJSON, err := json.Marshal(options.BuildArgs)
|
|
if err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("buildargs", string(buildArgsJSON))
|
|
|
|
labelsJSON, err := json.Marshal(options.Labels)
|
|
if err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("labels", string(labelsJSON))
|
|
|
|
cacheFromJSON, err := json.Marshal(options.CacheFrom)
|
|
if err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("cachefrom", string(cacheFromJSON))
|
|
if options.SessionID != "" {
|
|
query.Set("session", options.SessionID)
|
|
}
|
|
if options.Platform != "" {
|
|
if err := cli.NewVersionError(ctx, "1.32", "platform"); err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("platform", strings.ToLower(options.Platform))
|
|
}
|
|
if options.BuildID != "" {
|
|
query.Set("buildid", options.BuildID)
|
|
}
|
|
query.Set("version", string(options.Version))
|
|
|
|
if options.Outputs != nil {
|
|
outputsJSON, err := json.Marshal(options.Outputs)
|
|
if err != nil {
|
|
return query, err
|
|
}
|
|
query.Set("outputs", string(outputsJSON))
|
|
}
|
|
return query, nil
|
|
}
|