f688b73835
dockerfile.Config is almost redundant with ImageBuildOptions. Unify the two so that the latter can be removed. This also helps build's API endpoint code to be less dependent on package dockerfile. Signed-off-by: Anusha Ragunathan <anusha@docker.com> Upstream-commit: 5190794f1d85d5406611eb69c270df62ac1cdc7f Component: engine
128 lines
3.2 KiB
Go
128 lines
3.2 KiB
Go
package lib
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/url"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/docker/docker/api/types/container"
|
|
)
|
|
|
|
var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
|
|
|
|
// ImageBuild sends request to the daemon to build images.
|
|
// The Body in the response implement an io.ReadCloser and it's up to the caller to
|
|
// close it.
|
|
func (cli *Client) ImageBuild(options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
|
|
query, err := imageBuildOptionsToQuery(options)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
|
|
headers := http.Header(make(map[string][]string))
|
|
buf, err := json.Marshal(options.AuthConfigs)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))
|
|
headers.Set("Content-Type", "application/tar")
|
|
|
|
serverResp, err := cli.postRaw("/build", query, options.Context, headers)
|
|
if err != nil {
|
|
return types.ImageBuildResponse{}, err
|
|
}
|
|
|
|
osType := getDockerOS(serverResp.header.Get("Server"))
|
|
|
|
return types.ImageBuildResponse{
|
|
Body: serverResp.body,
|
|
OSType: osType,
|
|
}, nil
|
|
}
|
|
|
|
func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, error) {
|
|
query := url.Values{
|
|
"t": options.Tags,
|
|
}
|
|
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 !container.IsolationLevel.IsDefault(options.IsolationLevel) {
|
|
query.Set("isolation", string(options.IsolationLevel))
|
|
}
|
|
|
|
query.Set("cpusetcpus", options.CPUSetCPUs)
|
|
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)
|
|
|
|
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))
|
|
|
|
return query, nil
|
|
}
|
|
|
|
func getDockerOS(serverHeader string) string {
|
|
var osType string
|
|
matches := headerRegexp.FindStringSubmatch(serverHeader)
|
|
if len(matches) > 0 {
|
|
osType = matches[1]
|
|
}
|
|
return osType
|
|
}
|
|
|
|
// convertKVStringsToMap converts ["key=value"] to {"key":"value"}
|
|
func convertKVStringsToMap(values []string) map[string]string {
|
|
result := make(map[string]string, len(values))
|
|
for _, value := range values {
|
|
kv := strings.SplitN(value, "=", 2)
|
|
if len(kv) == 1 {
|
|
result[kv[0]] = ""
|
|
} else {
|
|
result[kv[0]] = kv[1]
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|