Browse code

Use ImageBuildOptions in builder.

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>

Anusha Ragunathan authored on 2015/12/30 05:49:17
Showing 14 changed files
... ...
@@ -16,6 +16,7 @@ import (
16 16
 
17 17
 	"github.com/docker/docker/api"
18 18
 	"github.com/docker/docker/api/types"
19
+	"github.com/docker/docker/api/types/container"
19 20
 	"github.com/docker/docker/builder/dockerignore"
20 21
 	Cli "github.com/docker/docker/cli"
21 22
 	"github.com/docker/docker/opts"
... ...
@@ -207,6 +208,14 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
207 207
 		}
208 208
 	}
209 209
 
210
+	var shmSize int64
211
+	if *flShmSize != "" {
212
+		shmSize, err = units.RAMInBytes(*flShmSize)
213
+		if err != nil {
214
+			return err
215
+		}
216
+	}
217
+
210 218
 	var remoteContext string
211 219
 	if isRemote {
212 220
 		remoteContext = cmd.Arg(0)
... ...
@@ -223,17 +232,17 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
223 223
 		Remove:         *rm,
224 224
 		ForceRemove:    *forceRm,
225 225
 		PullParent:     *pull,
226
-		Isolation:      *isolation,
226
+		IsolationLevel: container.IsolationLevel(*isolation),
227 227
 		CPUSetCPUs:     *flCPUSetCpus,
228 228
 		CPUSetMems:     *flCPUSetMems,
229 229
 		CPUShares:      *flCPUShares,
230 230
 		CPUQuota:       *flCPUQuota,
231 231
 		CPUPeriod:      *flCPUPeriod,
232 232
 		CgroupParent:   *flCgroupParent,
233
-		ShmSize:        *flShmSize,
234 233
 		Dockerfile:     relDockerfile,
234
+		ShmSize:        shmSize,
235 235
 		Ulimits:        flUlimits.GetList(),
236
-		BuildArgs:      flBuildArg.GetAll(),
236
+		BuildArgs:      runconfigopts.ConvertKVStringsToMap(flBuildArg.GetAll()),
237 237
 		AuthConfigs:    cli.configFile.AuthConfigs,
238 238
 	}
239 239
 
... ...
@@ -11,7 +11,6 @@ import (
11 11
 
12 12
 	"github.com/docker/docker/api/types"
13 13
 	"github.com/docker/docker/api/types/container"
14
-	"github.com/docker/go-units"
15 14
 )
16 15
 
17 16
 var headerRegexp = regexp.MustCompile(`\ADocker/.+\s\((.+)\)\z`)
... ...
@@ -73,8 +72,8 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
73 73
 		query.Set("pull", "1")
74 74
 	}
75 75
 
76
-	if !container.IsolationLevel.IsDefault(container.IsolationLevel(options.Isolation)) {
77
-		query.Set("isolation", options.Isolation)
76
+	if !container.IsolationLevel.IsDefault(options.IsolationLevel) {
77
+		query.Set("isolation", string(options.IsolationLevel))
78 78
 	}
79 79
 
80 80
 	query.Set("cpusetcpus", options.CPUSetCPUs)
... ...
@@ -85,15 +84,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
85 85
 	query.Set("memory", strconv.FormatInt(options.Memory, 10))
86 86
 	query.Set("memswap", strconv.FormatInt(options.MemorySwap, 10))
87 87
 	query.Set("cgroupparent", options.CgroupParent)
88
-
89
-	if options.ShmSize != "" {
90
-		parsedShmSize, err := units.RAMInBytes(options.ShmSize)
91
-		if err != nil {
92
-			return query, err
93
-		}
94
-		query.Set("shmsize", strconv.FormatInt(parsedShmSize, 10))
95
-	}
96
-
88
+	query.Set("shmsize", strconv.FormatInt(options.ShmSize, 10))
97 89
 	query.Set("dockerfile", options.Dockerfile)
98 90
 
99 91
 	ulimitsJSON, err := json.Marshal(options.Ulimits)
... ...
@@ -102,8 +93,7 @@ func imageBuildOptionsToQuery(options types.ImageBuildOptions) (url.Values, erro
102 102
 	}
103 103
 	query.Set("ulimits", string(ulimitsJSON))
104 104
 
105
-	buildArgs := convertKVStringsToMap(options.BuildArgs)
106
-	buildArgsJSON, err := json.Marshal(buildArgs)
105
+	buildArgsJSON, err := json.Marshal(options.BuildArgs)
107 106
 	if err != nil {
108 107
 		return query, err
109 108
 	}
... ...
@@ -68,11 +68,72 @@ func sanitizeRepoAndTags(names []string) ([]reference.Named, error) {
68 68
 	return repoAndTags, nil
69 69
 }
70 70
 
71
+func newImageBuildOptions(ctx context.Context, r *http.Request) (*types.ImageBuildOptions, error) {
72
+	version := httputils.VersionFromContext(ctx)
73
+	options := &types.ImageBuildOptions{}
74
+	if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
75
+		options.Remove = true
76
+	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
77
+		options.Remove = true
78
+	} else {
79
+		options.Remove = httputils.BoolValue(r, "rm")
80
+	}
81
+	if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
82
+		options.PullParent = true
83
+	}
84
+
85
+	options.Dockerfile = r.FormValue("dockerfile")
86
+	options.SuppressOutput = httputils.BoolValue(r, "q")
87
+	options.NoCache = httputils.BoolValue(r, "nocache")
88
+	options.ForceRemove = httputils.BoolValue(r, "forcerm")
89
+	options.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
90
+	options.Memory = httputils.Int64ValueOrZero(r, "memory")
91
+	options.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
92
+	options.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
93
+	options.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
94
+	options.CPUSetCPUs = r.FormValue("cpusetcpus")
95
+	options.CPUSetMems = r.FormValue("cpusetmems")
96
+	options.CgroupParent = r.FormValue("cgroupparent")
97
+
98
+	if r.Form.Get("shmsize") != "" {
99
+		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
100
+		if err != nil {
101
+			return nil, err
102
+		}
103
+		options.ShmSize = shmSize
104
+	}
105
+
106
+	if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
107
+		if !container.IsolationLevel.IsValid(i) {
108
+			return nil, fmt.Errorf("Unsupported isolation: %q", i)
109
+		}
110
+		options.IsolationLevel = i
111
+	}
112
+
113
+	var buildUlimits = []*units.Ulimit{}
114
+	ulimitsJSON := r.FormValue("ulimits")
115
+	if ulimitsJSON != "" {
116
+		if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
117
+			return nil, err
118
+		}
119
+		options.Ulimits = buildUlimits
120
+	}
121
+
122
+	var buildArgs = map[string]string{}
123
+	buildArgsJSON := r.FormValue("buildargs")
124
+	if buildArgsJSON != "" {
125
+		if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
126
+			return nil, err
127
+		}
128
+		options.BuildArgs = buildArgs
129
+	}
130
+	return options, nil
131
+}
132
+
71 133
 func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
72 134
 	var (
73 135
 		authConfigs        = map[string]types.AuthConfig{}
74 136
 		authConfigsEncoded = r.Header.Get("X-Registry-Config")
75
-		buildConfig        = &dockerfile.Config{}
76 137
 		notVerboseBuffer   = bytes.NewBuffer(nil)
77 138
 	)
78 139
 
... ...
@@ -87,12 +148,11 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
87 87
 
88 88
 	w.Header().Set("Content-Type", "application/json")
89 89
 
90
-	version := httputils.VersionFromContext(ctx)
91 90
 	output := ioutils.NewWriteFlusher(w)
92 91
 	defer output.Close()
93 92
 	sf := streamformatter.NewJSONStreamFormatter()
94 93
 	errf := func(err error) error {
95
-		if !buildConfig.Verbose && notVerboseBuffer.Len() > 0 {
94
+		if httputils.BoolValue(r, "q") && notVerboseBuffer.Len() > 0 {
96 95
 			output.Write(notVerboseBuffer.Bytes())
97 96
 		}
98 97
 		// 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 *
107 107
 		return nil
108 108
 	}
109 109
 
110
-	if httputils.BoolValue(r, "forcerm") && version.GreaterThanOrEqualTo("1.12") {
111
-		buildConfig.Remove = true
112
-	} else if r.FormValue("rm") == "" && version.GreaterThanOrEqualTo("1.12") {
113
-		buildConfig.Remove = true
114
-	} else {
115
-		buildConfig.Remove = httputils.BoolValue(r, "rm")
116
-	}
117
-	if httputils.BoolValue(r, "pull") && version.GreaterThanOrEqualTo("1.16") {
118
-		buildConfig.Pull = true
110
+	buildOptions, err := newImageBuildOptions(ctx, r)
111
+	if err != nil {
112
+		return errf(err)
119 113
 	}
120 114
 
121 115
 	repoAndTags, err := sanitizeRepoAndTags(r.Form["t"])
... ...
@@ -123,59 +177,13 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
123 123
 		return errf(err)
124 124
 	}
125 125
 
126
-	buildConfig.DockerfileName = r.FormValue("dockerfile")
127
-	buildConfig.Verbose = !httputils.BoolValue(r, "q")
128
-	buildConfig.UseCache = !httputils.BoolValue(r, "nocache")
129
-	buildConfig.ForceRemove = httputils.BoolValue(r, "forcerm")
130
-	buildConfig.MemorySwap = httputils.Int64ValueOrZero(r, "memswap")
131
-	buildConfig.Memory = httputils.Int64ValueOrZero(r, "memory")
132
-	buildConfig.CPUShares = httputils.Int64ValueOrZero(r, "cpushares")
133
-	buildConfig.CPUPeriod = httputils.Int64ValueOrZero(r, "cpuperiod")
134
-	buildConfig.CPUQuota = httputils.Int64ValueOrZero(r, "cpuquota")
135
-	buildConfig.CPUSetCpus = r.FormValue("cpusetcpus")
136
-	buildConfig.CPUSetMems = r.FormValue("cpusetmems")
137
-	buildConfig.CgroupParent = r.FormValue("cgroupparent")
138
-
139
-	if r.Form.Get("shmsize") != "" {
140
-		shmSize, err := strconv.ParseInt(r.Form.Get("shmsize"), 10, 64)
141
-		if err != nil {
142
-			return errf(err)
143
-		}
144
-		buildConfig.ShmSize = &shmSize
145
-	}
146
-
147
-	if i := container.IsolationLevel(r.FormValue("isolation")); i != "" {
148
-		if !container.IsolationLevel.IsValid(i) {
149
-			return errf(fmt.Errorf("Unsupported isolation: %q", i))
150
-		}
151
-		buildConfig.Isolation = i
152
-	}
153
-
154
-	var buildUlimits = []*units.Ulimit{}
155
-	ulimitsJSON := r.FormValue("ulimits")
156
-	if ulimitsJSON != "" {
157
-		if err := json.NewDecoder(strings.NewReader(ulimitsJSON)).Decode(&buildUlimits); err != nil {
158
-			return errf(err)
159
-		}
160
-		buildConfig.Ulimits = buildUlimits
161
-	}
162
-
163
-	var buildArgs = map[string]string{}
164
-	buildArgsJSON := r.FormValue("buildargs")
165
-	if buildArgsJSON != "" {
166
-		if err := json.NewDecoder(strings.NewReader(buildArgsJSON)).Decode(&buildArgs); err != nil {
167
-			return errf(err)
168
-		}
169
-		buildConfig.BuildArgs = buildArgs
170
-	}
171
-
172 126
 	remoteURL := r.FormValue("remote")
173 127
 
174 128
 	// Currently, only used if context is from a remote url.
175 129
 	// Look at code in DetectContextFromRemoteURL for more information.
176 130
 	createProgressReader := func(in io.ReadCloser) io.ReadCloser {
177 131
 		progressOutput := sf.NewProgressOutput(output, true)
178
-		if !buildConfig.Verbose {
132
+		if buildOptions.SuppressOutput {
179 133
 			progressOutput = sf.NewProgressOutput(notVerboseBuffer, true)
180 134
 		}
181 135
 		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 *
194 194
 			logrus.Debugf("[BUILDER] failed to remove temporary context: %v", err)
195 195
 		}
196 196
 	}()
197
+	if len(dockerfileName) > 0 {
198
+		buildOptions.Dockerfile = dockerfileName
199
+	}
197 200
 
198 201
 	uidMaps, gidMaps := br.backend.GetUIDGIDMaps()
199 202
 	defaultArchiver := &archive.Archiver{
... ...
@@ -201,23 +212,28 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
201 201
 		UIDMaps: uidMaps,
202 202
 		GIDMaps: gidMaps,
203 203
 	}
204
+
204 205
 	docker := &daemonbuilder.Docker{
205 206
 		Daemon:      br.backend,
206 207
 		OutOld:      output,
207 208
 		AuthConfigs: authConfigs,
208 209
 		Archiver:    defaultArchiver,
209 210
 	}
210
-	if !buildConfig.Verbose {
211
+	if buildOptions.SuppressOutput {
211 212
 		docker.OutOld = notVerboseBuffer
212 213
 	}
213 214
 
214
-	b, err := dockerfile.NewBuilder(buildConfig, docker, builder.DockerIgnoreContext{ModifiableContext: context}, nil)
215
+	b, err := dockerfile.NewBuilder(
216
+		buildOptions, // result of newBuildConfig
217
+		docker,
218
+		builder.DockerIgnoreContext{ModifiableContext: context},
219
+		nil)
215 220
 	if err != nil {
216 221
 		return errf(err)
217 222
 	}
218 223
 	b.Stdout = &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
219 224
 	b.Stderr = &streamformatter.StderrFormatter{Writer: output, StreamFormatter: sf}
220
-	if !buildConfig.Verbose {
225
+	if buildOptions.SuppressOutput {
221 226
 		b.Stdout = &streamformatter.StdoutFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
222 227
 		b.Stderr = &streamformatter.StderrFormatter{Writer: notVerboseBuffer, StreamFormatter: sf}
223 228
 	}
... ...
@@ -235,10 +251,6 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
235 235
 		}()
236 236
 	}
237 237
 
238
-	if len(dockerfileName) > 0 {
239
-		b.DockerfileName = dockerfileName
240
-	}
241
-
242 238
 	imgID, err := b.Build()
243 239
 	if err != nil {
244 240
 		return errf(err)
... ...
@@ -252,7 +264,7 @@ func (br *buildRouter) postBuild(ctx context.Context, w http.ResponseWriter, r *
252 252
 
253 253
 	// Everything worked so if -q was provided the output from the daemon
254 254
 	// should be just the image ID and we'll print that to stdout.
255
-	if !buildConfig.Verbose {
255
+	if buildOptions.SuppressOutput {
256 256
 		stdout := &streamformatter.StdoutFormatter{Writer: output, StreamFormatter: sf}
257 257
 		fmt.Fprintf(stdout, "%s\n", string(imgID))
258 258
 	}
... ...
@@ -127,7 +127,7 @@ type ImageBuildOptions struct {
127 127
 	Remove         bool
128 128
 	ForceRemove    bool
129 129
 	PullParent     bool
130
-	Isolation      string
130
+	IsolationLevel container.IsolationLevel
131 131
 	CPUSetCPUs     string
132 132
 	CPUSetMems     string
133 133
 	CPUShares      int64
... ...
@@ -136,10 +136,10 @@ type ImageBuildOptions struct {
136 136
 	Memory         int64
137 137
 	MemorySwap     int64
138 138
 	CgroupParent   string
139
-	ShmSize        string
139
+	ShmSize        int64
140 140
 	Dockerfile     string
141 141
 	Ulimits        []*units.Ulimit
142
-	BuildArgs      []string
142
+	BuildArgs      map[string]string
143 143
 	AuthConfigs    map[string]AuthConfig
144 144
 	Context        io.Reader
145 145
 }
... ...
@@ -216,7 +216,7 @@ type HostConfig struct {
216 216
 	SecurityOpt     []string           // List of string values to customize labels for MLS systems, such as SELinux.
217 217
 	Tmpfs           map[string]string  `json:",omitempty"` // List of tmpfs (mounts) used for the container
218 218
 	UTSMode         UTSMode            // UTS namespace to use for the container
219
-	ShmSize         *int64             // Total shm memory usage
219
+	ShmSize         int64              // Total shm memory usage
220 220
 
221 221
 	// Applicable to Windows
222 222
 	ConsoleSize [2]int         // Initial console size
... ...
@@ -10,11 +10,11 @@ import (
10 10
 	"sync"
11 11
 
12 12
 	"github.com/Sirupsen/logrus"
13
+	"github.com/docker/docker/api/types"
13 14
 	"github.com/docker/docker/api/types/container"
14 15
 	"github.com/docker/docker/builder"
15 16
 	"github.com/docker/docker/builder/dockerfile/parser"
16 17
 	"github.com/docker/docker/pkg/stringid"
17
-	"github.com/docker/go-units"
18 18
 )
19 19
 
20 20
 var validCommitCommands = map[string]bool{
... ...
@@ -41,38 +41,10 @@ var BuiltinAllowedBuildArgs = map[string]bool{
41 41
 	"no_proxy":    true,
42 42
 }
43 43
 
44
-// Config constitutes the configuration for a Dockerfile builder.
45
-type Config struct {
46
-	// only used if Dockerfile has to be extracted from Context
47
-	DockerfileName string
48
-
49
-	Verbose     bool
50
-	UseCache    bool
51
-	Remove      bool
52
-	ForceRemove bool
53
-	Pull        bool
54
-	BuildArgs   map[string]string // build-time args received in build context for expansion/substitution and commands in 'run'.
55
-	Isolation   container.IsolationLevel
56
-
57
-	// resource constraints
58
-	// TODO: factor out to be reused with Run ?
59
-
60
-	Memory       int64
61
-	MemorySwap   int64
62
-	ShmSize      *int64
63
-	CPUShares    int64
64
-	CPUPeriod    int64
65
-	CPUQuota     int64
66
-	CPUSetCpus   string
67
-	CPUSetMems   string
68
-	CgroupParent string
69
-	Ulimits      []*units.Ulimit
70
-}
71
-
72 44
 // Builder is a Dockerfile builder
73 45
 // It implements the builder.Backend interface.
74 46
 type Builder struct {
75
-	*Config
47
+	options *types.ImageBuildOptions
76 48
 
77 49
 	Stdout io.Writer
78 50
 	Stderr io.Writer
... ...
@@ -101,18 +73,18 @@ type Builder struct {
101 101
 // NewBuilder creates a new Dockerfile builder from an optional dockerfile and a Config.
102 102
 // If dockerfile is nil, the Dockerfile specified by Config.DockerfileName,
103 103
 // will be read from the Context passed to Build().
104
-func NewBuilder(config *Config, docker builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
104
+func NewBuilder(config *types.ImageBuildOptions, backend builder.Backend, context builder.Context, dockerfile io.ReadCloser) (b *Builder, err error) {
105 105
 	if config == nil {
106
-		config = new(Config)
106
+		config = new(types.ImageBuildOptions)
107 107
 	}
108 108
 	if config.BuildArgs == nil {
109 109
 		config.BuildArgs = make(map[string]string)
110 110
 	}
111 111
 	b = &Builder{
112
-		Config:           config,
112
+		options:          config,
113 113
 		Stdout:           os.Stdout,
114 114
 		Stderr:           os.Stderr,
115
-		docker:           docker,
115
+		docker:           backend,
116 116
 		context:          context,
117 117
 		runConfig:        new(container.Config),
118 118
 		tmpContainers:    map[string]struct{}{},
... ...
@@ -162,14 +134,14 @@ func (b *Builder) Build() (string, error) {
162 162
 			// Not cancelled yet, keep going...
163 163
 		}
164 164
 		if err := b.dispatch(i, n); err != nil {
165
-			if b.ForceRemove {
165
+			if b.options.ForceRemove {
166 166
 				b.clearTmp()
167 167
 			}
168 168
 			return "", err
169 169
 		}
170 170
 		shortImgID = stringid.TruncateID(b.image)
171 171
 		fmt.Fprintf(b.Stdout, " ---> %s\n", shortImgID)
172
-		if b.Remove {
172
+		if b.options.Remove {
173 173
 			b.clearTmp()
174 174
 		}
175 175
 	}
... ...
@@ -177,7 +149,7 @@ func (b *Builder) Build() (string, error) {
177 177
 	// check if there are any leftover build-args that were passed but not
178 178
 	// consumed during build. Return an error, if there are any.
179 179
 	leftoverArgs := []string{}
180
-	for arg := range b.BuildArgs {
180
+	for arg := range b.options.BuildArgs {
181 181
 		if !b.isBuildArgAllowed(arg) {
182 182
 			leftoverArgs = append(leftoverArgs, arg)
183 183
 		}
... ...
@@ -209,7 +209,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
209 209
 		err   error
210 210
 	)
211 211
 	// TODO: don't use `name`, instead resolve it to a digest
212
-	if !b.Pull {
212
+	if !b.options.PullParent {
213 213
 		image, err = b.docker.GetImage(name)
214 214
 		// TODO: shouldn't we error out if error is different from "not found" ?
215 215
 	}
... ...
@@ -339,7 +339,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
339 339
 	// lookup for same image built with same build time environment.
340 340
 	cmdBuildEnv := []string{}
341 341
 	configEnv := runconfigopts.ConvertKVStringsToMap(b.runConfig.Env)
342
-	for key, val := range b.BuildArgs {
342
+	for key, val := range b.options.BuildArgs {
343 343
 		if !b.isBuildArgAllowed(key) {
344 344
 			// skip build-args that are not in allowed list, meaning they have
345 345
 			// not been defined by an "ARG" Dockerfile command yet.
... ...
@@ -622,8 +622,8 @@ func arg(b *Builder, args []string, attributes map[string]bool, original string)
622 622
 	// If there is a default value associated with this arg then add it to the
623 623
 	// b.buildArgs if one is not already passed to the builder. The args passed
624 624
 	// to builder override the default value of 'arg'.
625
-	if _, ok := b.BuildArgs[name]; !ok && hasDefault {
626
-		b.BuildArgs[name] = value
625
+	if _, ok := b.options.BuildArgs[name]; !ok && hasDefault {
626
+		b.options.BuildArgs[name] = value
627 627
 	}
628 628
 
629 629
 	return b.commit("", b.runConfig.Cmd, fmt.Sprintf("ARG %s", arg))
... ...
@@ -148,7 +148,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
148 148
 	// a subsequent one. So, putting the buildArgs list after the Config.Env
149 149
 	// list, in 'envs', is safe.
150 150
 	envs := b.runConfig.Env
151
-	for key, val := range b.BuildArgs {
151
+	for key, val := range b.options.BuildArgs {
152 152
 		if !b.isBuildArgAllowed(key) {
153 153
 			// skip build-args that are not in allowed list, meaning they have
154 154
 			// not been defined by an "ARG" Dockerfile command yet.
... ...
@@ -450,7 +450,7 @@ func (b *Builder) processImageFrom(img builder.Image) error {
450 450
 // If there is any error, it returns `(false, err)`.
451 451
 func (b *Builder) probeCache() (bool, error) {
452 452
 	c, ok := b.docker.(builder.ImageCache)
453
-	if !ok || !b.UseCache || b.cacheBusted {
453
+	if !ok || b.options.NoCache || b.cacheBusted {
454 454
 		return false, nil
455 455
 	}
456 456
 	cache, err := c.GetCachedImage(b.image, b.runConfig)
... ...
@@ -477,21 +477,21 @@ func (b *Builder) create() (string, error) {
477 477
 	b.runConfig.Image = b.image
478 478
 
479 479
 	resources := container.Resources{
480
-		CgroupParent: b.CgroupParent,
481
-		CPUShares:    b.CPUShares,
482
-		CPUPeriod:    b.CPUPeriod,
483
-		CPUQuota:     b.CPUQuota,
484
-		CpusetCpus:   b.CPUSetCpus,
485
-		CpusetMems:   b.CPUSetMems,
486
-		Memory:       b.Memory,
487
-		MemorySwap:   b.MemorySwap,
488
-		Ulimits:      b.Ulimits,
480
+		CgroupParent: b.options.CgroupParent,
481
+		CPUShares:    b.options.CPUShares,
482
+		CPUPeriod:    b.options.CPUPeriod,
483
+		CPUQuota:     b.options.CPUQuota,
484
+		CpusetCpus:   b.options.CPUSetCPUs,
485
+		CpusetMems:   b.options.CPUSetMems,
486
+		Memory:       b.options.Memory,
487
+		MemorySwap:   b.options.MemorySwap,
488
+		Ulimits:      b.options.Ulimits,
489 489
 	}
490 490
 
491 491
 	// TODO: why not embed a hostconfig in builder?
492 492
 	hostConfig := &container.HostConfig{
493
-		Isolation: b.Isolation,
494
-		ShmSize:   b.ShmSize,
493
+		Isolation: b.options.IsolationLevel,
494
+		ShmSize:   b.options.ShmSize,
495 495
 		Resources: resources,
496 496
 	}
497 497
 
... ...
@@ -587,20 +587,20 @@ func (b *Builder) readDockerfile() error {
587 587
 	// If no -f was specified then look for 'Dockerfile'. If we can't find
588 588
 	// that then look for 'dockerfile'.  If neither are found then default
589 589
 	// back to 'Dockerfile' and use that in the error message.
590
-	if b.DockerfileName == "" {
591
-		b.DockerfileName = api.DefaultDockerfileName
592
-		if _, _, err := b.context.Stat(b.DockerfileName); os.IsNotExist(err) {
593
-			lowercase := strings.ToLower(b.DockerfileName)
590
+	if b.options.Dockerfile == "" {
591
+		b.options.Dockerfile = api.DefaultDockerfileName
592
+		if _, _, err := b.context.Stat(b.options.Dockerfile); os.IsNotExist(err) {
593
+			lowercase := strings.ToLower(b.options.Dockerfile)
594 594
 			if _, _, err := b.context.Stat(lowercase); err == nil {
595
-				b.DockerfileName = lowercase
595
+				b.options.Dockerfile = lowercase
596 596
 			}
597 597
 		}
598 598
 	}
599 599
 
600
-	f, err := b.context.Open(b.DockerfileName)
600
+	f, err := b.context.Open(b.options.Dockerfile)
601 601
 	if err != nil {
602 602
 		if os.IsNotExist(err) {
603
-			return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.DockerfileName)
603
+			return fmt.Errorf("Cannot locate specified Dockerfile: %s", b.options.Dockerfile)
604 604
 		}
605 605
 		return err
606 606
 	}
... ...
@@ -611,7 +611,7 @@ func (b *Builder) readDockerfile() error {
611 611
 			return fmt.Errorf("Unexpected error reading Dockerfile: %v", err)
612 612
 		}
613 613
 		if fi.Size() == 0 {
614
-			return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.DockerfileName)
614
+			return fmt.Errorf("The Dockerfile (%s) cannot be empty", b.options.Dockerfile)
615 615
 		}
616 616
 	}
617 617
 	b.dockerfile, err = parser.Parse(f)
... ...
@@ -629,7 +629,7 @@ func (b *Builder) readDockerfile() error {
629 629
 	// Note that this assumes the Dockerfile has been read into memory and
630 630
 	// is now safe to be removed.
631 631
 	if dockerIgnore, ok := b.context.(builder.DockerIgnoreContext); ok {
632
-		dockerIgnore.Process([]string{b.DockerfileName})
632
+		dockerIgnore.Process([]string{b.options.Dockerfile})
633 633
 	}
634 634
 	return nil
635 635
 }
... ...
@@ -899,8 +899,8 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
899 899
 		}
900 900
 
901 901
 		shmSize := container.DefaultSHMSize
902
-		if c.HostConfig.ShmSize != nil {
903
-			shmSize = *c.HostConfig.ShmSize
902
+		if c.HostConfig.ShmSize != 0 {
903
+			shmSize = c.HostConfig.ShmSize
904 904
 		}
905 905
 		shmproperty := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
906 906
 		if err := syscall.Mount("shm", shmPath, "tmpfs", uintptr(syscall.MS_NOEXEC|syscall.MS_NOSUID|syscall.MS_NODEV), label.FormatMountLabel(shmproperty, c.GetMountLabel())); err != nil {
... ...
@@ -191,9 +191,8 @@ func (daemon *Daemon) adaptContainerSettings(hostConfig *containertypes.HostConf
191 191
 		// By default, MemorySwap is set to twice the size of Memory.
192 192
 		hostConfig.MemorySwap = hostConfig.Memory * 2
193 193
 	}
194
-	if hostConfig.ShmSize == nil {
195
-		shmSize := container.DefaultSHMSize
196
-		hostConfig.ShmSize = &shmSize
194
+	if hostConfig.ShmSize == 0 {
195
+		hostConfig.ShmSize = container.DefaultSHMSize
197 196
 	}
198 197
 	var err error
199 198
 	if hostConfig.SecurityOpt == nil {
... ...
@@ -365,7 +364,7 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
365 365
 	}
366 366
 	warnings = append(warnings, w...)
367 367
 
368
-	if hostConfig.ShmSize != nil && *hostConfig.ShmSize <= 0 {
368
+	if hostConfig.ShmSize < 0 {
369 369
 		return warnings, fmt.Errorf("SHM size must be greater then 0")
370 370
 	}
371 371
 
... ...
@@ -1403,18 +1403,6 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeNegative(c *check.C) {
1403 1403
 	c.Assert(string(body), checker.Contains, "SHM size must be greater then 0")
1404 1404
 }
1405 1405
 
1406
-func (s *DockerSuite) TestPostContainersCreateShmSizeZero(c *check.C) {
1407
-	config := map[string]interface{}{
1408
-		"Image":      "busybox",
1409
-		"HostConfig": map[string]interface{}{"ShmSize": 0},
1410
-	}
1411
-
1412
-	status, body, err := sockRequest("POST", "/containers/create", config)
1413
-	c.Assert(err, check.IsNil)
1414
-	c.Assert(status, check.Equals, http.StatusInternalServerError)
1415
-	c.Assert(string(body), checker.Contains, "SHM size must be greater then 0")
1416
-}
1417
-
1418 1406
 func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.C) {
1419 1407
 	var defaultSHMSize int64 = 67108864
1420 1408
 	config := map[string]interface{}{
... ...
@@ -1436,7 +1424,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeHostConfigOmitted(c *check.
1436 1436
 	var containerJSON types.ContainerJSON
1437 1437
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
1438 1438
 
1439
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, defaultSHMSize)
1439
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, defaultSHMSize)
1440 1440
 
1441 1441
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
1442 1442
 	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
... ...
@@ -1466,7 +1454,7 @@ func (s *DockerSuite) TestPostContainersCreateShmSizeOmitted(c *check.C) {
1466 1466
 	var containerJSON types.ContainerJSON
1467 1467
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
1468 1468
 
1469
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, int64(67108864))
1469
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, int64(67108864))
1470 1470
 
1471 1471
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
1472 1472
 	shmRegexp := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=65536k`)
... ...
@@ -1496,7 +1484,7 @@ func (s *DockerSuite) TestPostContainersCreateWithShmSize(c *check.C) {
1496 1496
 	var containerJSON types.ContainerJSON
1497 1497
 	c.Assert(json.Unmarshal(body, &containerJSON), check.IsNil)
1498 1498
 
1499
-	c.Assert(*containerJSON.HostConfig.ShmSize, check.Equals, int64(1073741824))
1499
+	c.Assert(containerJSON.HostConfig.ShmSize, check.Equals, int64(1073741824))
1500 1500
 
1501 1501
 	out, _ := dockerCmd(c, "start", "-i", containerJSON.ID)
1502 1502
 	shmRegex := regexp.MustCompile(`shm on /dev/shm type tmpfs(.*)size=1048576k`)
... ...
@@ -186,13 +186,12 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
186 186
 		return nil, nil, cmd, fmt.Errorf("Invalid value: %d. Valid memory swappiness range is 0-100", swappiness)
187 187
 	}
188 188
 
189
-	var parsedShm *int64
189
+	var shmSize int64
190 190
 	if *flShmSize != "" {
191
-		shmSize, err := units.RAMInBytes(*flShmSize)
191
+		shmSize, err = units.RAMInBytes(*flShmSize)
192 192
 		if err != nil {
193 193
 			return nil, nil, cmd, err
194 194
 		}
195
-		parsedShm = &shmSize
196 195
 	}
197 196
 
198 197
 	var binds []string
... ...
@@ -397,7 +396,7 @@ func Parse(cmd *flag.FlagSet, args []string) (*container.Config, *container.Host
397 397
 		LogConfig:      container.LogConfig{Type: *flLoggingDriver, Config: loggingOpts},
398 398
 		VolumeDriver:   *flVolumeDriver,
399 399
 		Isolation:      container.IsolationLevel(*flIsolation),
400
-		ShmSize:        parsedShm,
400
+		ShmSize:        shmSize,
401 401
 		Resources:      resources,
402 402
 		Tmpfs:          tmpfs,
403 403
 	}
... ...
@@ -535,8 +535,8 @@ func TestParseModes(t *testing.T) {
535 535
 	if err != nil {
536 536
 		t.Fatal(err)
537 537
 	}
538
-	if *hostconfig.ShmSize != 134217728 {
539
-		t.Fatalf("Expected a valid ShmSize, got %d", *hostconfig.ShmSize)
538
+	if hostconfig.ShmSize != 134217728 {
539
+		t.Fatalf("Expected a valid ShmSize, got %d", hostconfig.ShmSize)
540 540
 	}
541 541
 }
542 542