|
@@ -68,11 +68,72 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
|
|
|
return repoAndTags, nil
|
|
|
}
|
|
|
|
|
|
+func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
|
|
|
+ version := httputils.VersionFromContext(ctx)
|
|
|
+ options := &types.ImageBuildOptions{}
|
|
|
+ if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
|
|
|
+ options.Remove = true
|
|
|
+ } else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
|
|
|
+ options.Remove = true
|
|
|
+ } else {
|
|
|
+ options.Remove = httputils.BoolValue(r, "rm")
|
|
|
+ }
|
|
|
+ if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
|
|
|
+ options.PullParent = true
|
|
|
+ }
|
|
|
+
|
|
|
+ options.Dockerfile = r.FormValue("dockerfile")
|
|
|
+ options.SuppressOutput = httputils.BoolValue(r, "q")
|
|
|
+ options.NoCache = httputils.BoolValue(r, "nocache")
|
|
|
+ options.ForceRemove = httputils.BoolValue(r, "forcerm")
|
|
|
+ options.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
|
|
|
+ options.Memory = httputils.Int64ValueOrZero(r, "memory")
|
|
|
+ options.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
|
|
|
+ options.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
|
|
|
+ options.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
|
|
|
+ options.CPUSetCPUs = r.FormValue("cpusetcpus")
|
|
|
+ options.CPUSetMems = r.FormValue("cpusetmems")
|
|
|
+ options.CgroupParent = r.FormValue("cgroupparent")
|
|
|
+
|
|
|
+ if r.Form.Get("shmsize") != "" {
|
|
|
+ shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ options.ShmSize = shmSize
|
|
|
+ }
|
|
|
+
|
|
|
+ if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
|
|
|
+ if !container.IsolationLevel.IsValid(i) {
|
|
|
+ return nil, fmt.Errorf("Unsupported isolation: %q", i)
|
|
|
+ }
|
|
|
+ options.IsolationLevel = i
|
|
|
+ }
|
|
|
+
|
|
|
+ var buildUlimits = []*units.Ulimit{}
|
|
|
+ ulimitsJSON := r.FormValue("ulimits")
|
|
|
+ if ulimitsJSON != "" {
|
|
|
+ if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ options.Ulimits = buildUlimits
|
|
|
+ }
|
|
|
+
|
|
|
+ var buildArgs = map[string]string{}
|
|
|
+ buildArgsJSON := r.FormValue("buildargs")
|
|
|
+ if buildArgsJSON != "" {
|
|
|
+ if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ options.BuildArgs = buildArgs
|
|
|
+ }
|
|
|
+ return options, nil
|
|
|
+}
|
|
|
+
|
|
|
func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
|
|
var (
|
|
|
authConfigs = map[string]types.AuthConfig{}
|
|
|
authConfigsEncoded = r.Header.Get("X-Registry-Config")
|
|
|
- buildConfig = &dockerfile.Config{}
|
|
|
notVerboseBuffer = bytes.NewBuffer(nil)
|
|
|
)
|
|
|
|
|
@@ -87,12 +148,11 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
|
|
- version := httputils.VersionFromContext(ctx)
|
|
|
output := ioutils.NewWriteFlusher(w)
|
|
|
defer output.Close()
|
|
|
sf := streamformatter.NewJSONStreamFormatter()
|
|
|
errf := func(err error) error {
|
|
|
- if !buildConfig.Verbose && notVerboseBuffer.Len() > 0 {
|
|
|
+ if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
|
|
|
output.Write(notVerboseBuffer.Bytes())
|
|
|
}
|
|
|
// Do not write the error in the http output if it's still empty.
|
|
@@ -107,15 +167,9 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
|
|
|
- buildConfig.Remove = true
|
|
|
- } else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
|
|
|
- buildConfig.Remove = true
|
|
|
- } else {
|
|
|
- buildConfig.Remove = httputils.BoolValue(r, "rm")
|
|
|
- }
|
|
|
- if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
|
|
|
- buildConfig.Pull = true
|
|
|
+ buildOptions, err := newImageBuildOptions(ctx, r)
|
|
|
+ if err != nil {
|
|
|
+ return errf(err)
|
|
|
}
|
|
|
|
|
|
repoAndTags, err := sanitizeRepoAndTags(r.Form["t"])
|
|
@@ -123,59 +177,13 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
return errf(err)
|
|
|
}
|
|
|
|
|
|
- buildConfig.DockerfileName = r.FormValue("dockerfile")
|
|
|
- buildConfig.Verbose = !httputils.BoolValue(r, "q")
|
|
|
- buildConfig.UseCache = !httputils.BoolValue(r, "nocache")
|
|
|
- buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm")
|
|
|
- buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
|
|
|
- buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory")
|
|
|
- buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
|
|
|
- buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
|
|
|
- buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
|
|
|
- buildConfig.CPUSetCpus = r.FormValue("cpusetcpus")
|
|
|
- buildConfig.CPUSetMems = r.FormValue("cpusetmems")
|
|
|
- buildConfig.CgroupParent = r.FormValue("cgroupparent")
|
|
|
-
|
|
|
- if r.Form.Get("shmsize") != "" {
|
|
|
- shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
|
|
|
- if err != nil {
|
|
|
- return errf(err)
|
|
|
- }
|
|
|
- buildConfig.ShmSize = &shmSize
|
|
|
- }
|
|
|
-
|
|
|
- if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
|
|
|
- if !container.IsolationLevel.IsValid(i) {
|
|
|
- return errf(fmt.Errorf("Unsupported isolation: %q", i))
|
|
|
- }
|
|
|
- buildConfig.Isolation = i
|
|
|
- }
|
|
|
-
|
|
|
- var buildUlimits = []*units.Ulimit{}
|
|
|
- ulimitsJSON := r.FormValue("ulimits")
|
|
|
- if ulimitsJSON != "" {
|
|
|
- if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
|
|
|
- return errf(err)
|
|
|
- }
|
|
|
- buildConfig.Ulimits = buildUlimits
|
|
|
- }
|
|
|
-
|
|
|
- var buildArgs = map[string]string{}
|
|
|
- buildArgsJSON := r.FormValue("buildargs")
|
|
|
- if buildArgsJSON != "" {
|
|
|
- if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
|
|
|
- return errf(err)
|
|
|
- }
|
|
|
- buildConfig.BuildArgs = buildArgs
|
|
|
- }
|
|
|
-
|
|
|
remoteURL := r.FormValue("remote")
|
|
|
|
|
|
// Currently, only used if context is from a remote url.
|
|
|
// Look at code in DetectContextFromRemoteURL for more information.
|
|
|
createProgressReader := func(in io.ReadCloser) io.ReadCloser {
|
|
|
progressOutput := sf.NewProgressOutput(output, true)
|
|
|
- if !buildConfig.Verbose {
|
|
|
+ if buildOptions.SuppressOutput {
|
|
|
progressOutput = sf.NewProgressOutput(notVerboseBuffer, true)
|
|
|
}
|
|
|
return progress.NewProgressReader(in, progressOutput, r.ContentLength, "Downloading context", remoteURL)
|
|
@@ -194,6 +202,9 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
logrus.Debugf("[BUILDER] failed to remove temporary context: %v", err)
|
|
|
}
|
|
|
}()
|
|
|
+ if len(dockerfileName) > 0 {
|
|
|
+ buildOptions.Dockerfile = dockerfileName
|
|
|
+ }
|
|
|
|
|
|
uidMaps, gidMaps := br.backend.GetUIDGIDMaps()
|
|
|
defaultArchiver := &archive.Archiver{
|
|
@@ -201,23 +212,28 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
UIDMaps: uidMaps,
|
|
|
GIDMaps: gidMaps,
|
|
|
}
|
|
|
+
|
|
|
docker := &daemonbuilder.Docker{
|
|
|
Daemon: br.backend,
|
|
|
OutOld: output,
|
|
|
AuthConfigs: authConfigs,
|
|
|
Archiver: defaultArchiver,
|
|
|
}
|
|
|
- if !buildConfig.Verbose {
|
|
|
+ if buildOptions.SuppressOutput {
|
|
|
docker.OutOld = notVerboseBuffer
|
|
|
}
|
|
|
|
|
|
- b, err := dockerfile.NewBuilder(buildConfig, docker, builder.DockerIgnoreContext{ModifiableContext: context}, nil)
|
|
|
+ b, err := dockerfile.NewBuilder(
|
|
|
+ buildOptions, // result of newBuildConfig
|
|
|
+ docker,
|
|
|
+ builder.DockerIgnoreContext{ModifiableContext: context},
|
|
|
+ nil)
|
|
|
if err != nil {
|
|
|
return errf(err)
|
|
|
}
|
|
|
b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
|
|
|
b.Stderr = &streamformatter.StderrFormatter{Writer: output, StreamFormatter: sf}
|
|
|
- if !buildConfig.Verbose {
|
|
|
+ if buildOptions.SuppressOutput {
|
|
|
b.Stdout = &streamformatter.StdoutFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
|
|
|
b.Stderr = &streamformatter.StderrFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
|
|
|
}
|
|
@@ -235,10 +251,6 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
}()
|
|
|
}
|
|
|
|
|
|
- if len(dockerfileName) > 0 {
|
|
|
- b.DockerfileName = dockerfileName
|
|
|
- }
|
|
|
-
|
|
|
imgID, err := b.Build()
|
|
|
if err != nil {
|
|
|
return errf(err)
|
|
@@ -252,7 +264,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
|
|
|
|
|
|
// Everything worked so if -q was provided the output from the daemon
|
|
|
// should be just the image ID and we'll print that to stdout.
|
|
|
- if !buildConfig.Verbose {
|
|
|
+ if buildOptions.SuppressOutput {
|
|
|
stdout := &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
|
|
|
fmt.Fprintf(stdout, "%s\n", string(imgID))
|
|
|
}
|