Remove unused arguments to commit.
This will allow us to remove all the runConfig mutate+revert code that
is scattered around builder dispatchers/internals
Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -73,7 +73,7 @@ func env(req dispatchRequest) error {
|
| 73 | 73 |
} |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 |
- return req.builder.commit("", req.runConfig.Cmd, commitMessage.String())
|
|
| 76 |
+ return req.builder.commit(commitMessage.String()) |
|
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 | 79 |
// MAINTAINER some text <maybe@an.email.address> |
| ... | ... |
@@ -90,7 +90,7 @@ func maintainer(req dispatchRequest) error {
|
| 90 | 90 |
|
| 91 | 91 |
maintainer := req.args[0] |
| 92 | 92 |
req.builder.maintainer = maintainer |
| 93 |
- return req.builder.commit("", req.runConfig.Cmd, "MAINTAINER "+maintainer)
|
|
| 93 |
+ return req.builder.commit("MAINTAINER " + maintainer)
|
|
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 | 96 |
// LABEL some json data describing the image |
| ... | ... |
@@ -130,7 +130,7 @@ func label(req dispatchRequest) error {
|
| 130 | 130 |
req.runConfig.Labels[req.args[j]] = req.args[j+1] |
| 131 | 131 |
j++ |
| 132 | 132 |
} |
| 133 |
- return req.builder.commit("", req.runConfig.Cmd, commitStr)
|
|
| 133 |
+ return req.builder.commit(commitStr) |
|
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
// ADD foo /path |
| ... | ... |
@@ -281,7 +281,7 @@ func onbuild(req dispatchRequest) error {
|
| 281 | 281 |
|
| 282 | 282 |
original := regexp.MustCompile(`(?i)^\s*ONBUILD\s*`).ReplaceAllString(req.original, "") |
| 283 | 283 |
req.runConfig.OnBuild = append(req.runConfig.OnBuild, original) |
| 284 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("ONBUILD %s", original))
|
|
| 284 |
+ return req.builder.commit("ONBUILD " + original)
|
|
| 285 | 285 |
} |
| 286 | 286 |
|
| 287 | 287 |
// WORKDIR /tmp |
| ... | ... |
@@ -321,10 +321,9 @@ func workdir(req dispatchRequest) error {
|
| 321 | 321 |
req.runConfig.Cmd = strslice.StrSlice(append(getShell(req.runConfig), "#(nop) "+comment)) |
| 322 | 322 |
defer func(cmd strslice.StrSlice) { req.runConfig.Cmd = cmd }(cmd)
|
| 323 | 323 |
|
| 324 |
- if hit, err := req.builder.probeCache(); err != nil {
|
|
| 324 |
+ // TODO: this should pass a copy of runConfig |
|
| 325 |
+ if hit, err := req.builder.probeCache(req.builder.image, req.runConfig); err != nil || hit {
|
|
| 325 | 326 |
return err |
| 326 |
- } else if hit {
|
|
| 327 |
- return nil |
|
| 328 | 327 |
} |
| 329 | 328 |
|
| 330 | 329 |
req.runConfig.Image = req.builder.image |
| ... | ... |
@@ -341,7 +340,7 @@ func workdir(req dispatchRequest) error {
|
| 341 | 341 |
return err |
| 342 | 342 |
} |
| 343 | 343 |
|
| 344 |
- return req.builder.commit(container.ID, cmd, comment) |
|
| 344 |
+ return req.builder.commitContainer(container.ID, copyRunConfig(req.runConfig, withCmd(cmd))) |
|
| 345 | 345 |
} |
| 346 | 346 |
|
| 347 | 347 |
// RUN some command yo |
| ... | ... |
@@ -402,13 +401,10 @@ func run(req dispatchRequest) error {
|
| 402 | 402 |
} |
| 403 | 403 |
|
| 404 | 404 |
req.runConfig.Cmd = saveCmd |
| 405 |
- hit, err := req.builder.probeCache() |
|
| 406 |
- if err != nil {
|
|
| 405 |
+ hit, err := req.builder.probeCache(req.builder.image, req.runConfig) |
|
| 406 |
+ if err != nil || hit {
|
|
| 407 | 407 |
return err |
| 408 | 408 |
} |
| 409 |
- if hit {
|
|
| 410 |
- return nil |
|
| 411 |
- } |
|
| 412 | 409 |
|
| 413 | 410 |
// set Cmd manually, this is special case only for Dockerfiles |
| 414 | 411 |
req.runConfig.Cmd = config.Cmd |
| ... | ... |
@@ -419,7 +415,11 @@ func run(req dispatchRequest) error {
|
| 419 | 419 |
|
| 420 | 420 |
logrus.Debugf("[BUILDER] Command to be executed: %v", req.runConfig.Cmd)
|
| 421 | 421 |
|
| 422 |
- cID, err := req.builder.create() |
|
| 422 |
+ // TODO: this was previously in b.create(), why is it necessary? |
|
| 423 |
+ req.builder.runConfig.Image = req.builder.image |
|
| 424 |
+ |
|
| 425 |
+ // TODO: should pass a copy of runConfig |
|
| 426 |
+ cID, err := req.builder.create(req.runConfig) |
|
| 423 | 427 |
if err != nil {
|
| 424 | 428 |
return err |
| 425 | 429 |
} |
| ... | ... |
@@ -451,7 +451,7 @@ func run(req dispatchRequest) error {
|
| 451 | 451 |
saveCmd = strslice.StrSlice(append(tmpEnv, saveCmd...)) |
| 452 | 452 |
} |
| 453 | 453 |
req.runConfig.Cmd = saveCmd |
| 454 |
- return req.builder.commit(cID, cmd, "run") |
|
| 454 |
+ return req.builder.commitContainer(cID, copyRunConfig(req.runConfig, withCmd(cmd))) |
|
| 455 | 455 |
} |
| 456 | 456 |
|
| 457 | 457 |
// CMD foo |
| ... | ... |
@@ -474,7 +474,7 @@ func cmd(req dispatchRequest) error {
|
| 474 | 474 |
// set config as already being escaped, this prevents double escaping on windows |
| 475 | 475 |
req.runConfig.ArgsEscaped = true |
| 476 | 476 |
|
| 477 |
- if err := req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("CMD %q", cmdSlice)); err != nil {
|
|
| 477 |
+ if err := req.builder.commit(fmt.Sprintf("CMD %q", cmdSlice)); err != nil {
|
|
| 478 | 478 |
return err |
| 479 | 479 |
} |
| 480 | 480 |
|
| ... | ... |
@@ -590,7 +590,7 @@ func healthcheck(req dispatchRequest) error {
|
| 590 | 590 |
req.runConfig.Healthcheck = &healthcheck |
| 591 | 591 |
} |
| 592 | 592 |
|
| 593 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("HEALTHCHECK %q", req.runConfig.Healthcheck))
|
|
| 593 |
+ return req.builder.commit(fmt.Sprintf("HEALTHCHECK %q", req.runConfig.Healthcheck))
|
|
| 594 | 594 |
} |
| 595 | 595 |
|
| 596 | 596 |
// ENTRYPOINT /usr/sbin/nginx |
| ... | ... |
@@ -626,11 +626,7 @@ func entrypoint(req dispatchRequest) error {
|
| 626 | 626 |
req.runConfig.Cmd = nil |
| 627 | 627 |
} |
| 628 | 628 |
|
| 629 |
- if err := req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("ENTRYPOINT %q", req.runConfig.Entrypoint)); err != nil {
|
|
| 630 |
- return err |
|
| 631 |
- } |
|
| 632 |
- |
|
| 633 |
- return nil |
|
| 629 |
+ return req.builder.commit(fmt.Sprintf("ENTRYPOINT %q", req.runConfig.Entrypoint))
|
|
| 634 | 630 |
} |
| 635 | 631 |
|
| 636 | 632 |
// EXPOSE 6667/tcp 7000/tcp |
| ... | ... |
@@ -671,7 +667,7 @@ func expose(req dispatchRequest) error {
|
| 671 | 671 |
i++ |
| 672 | 672 |
} |
| 673 | 673 |
sort.Strings(portList) |
| 674 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("EXPOSE %s", strings.Join(portList, " ")))
|
|
| 674 |
+ return req.builder.commit("EXPOSE " + strings.Join(portList, " "))
|
|
| 675 | 675 |
} |
| 676 | 676 |
|
| 677 | 677 |
// USER foo |
| ... | ... |
@@ -689,7 +685,7 @@ func user(req dispatchRequest) error {
|
| 689 | 689 |
} |
| 690 | 690 |
|
| 691 | 691 |
req.runConfig.User = req.args[0] |
| 692 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("USER %v", req.args))
|
|
| 692 |
+ return req.builder.commit(fmt.Sprintf("USER %v", req.args))
|
|
| 693 | 693 |
} |
| 694 | 694 |
|
| 695 | 695 |
// VOLUME /foo |
| ... | ... |
@@ -715,10 +711,7 @@ func volume(req dispatchRequest) error {
|
| 715 | 715 |
} |
| 716 | 716 |
req.runConfig.Volumes[v] = struct{}{}
|
| 717 | 717 |
} |
| 718 |
- if err := req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("VOLUME %v", req.args)); err != nil {
|
|
| 719 |
- return err |
|
| 720 |
- } |
|
| 721 |
- return nil |
|
| 718 |
+ return req.builder.commit(fmt.Sprintf("VOLUME %v", req.args))
|
|
| 722 | 719 |
} |
| 723 | 720 |
|
| 724 | 721 |
// STOPSIGNAL signal |
| ... | ... |
@@ -736,7 +729,7 @@ func stopSignal(req dispatchRequest) error {
|
| 736 | 736 |
} |
| 737 | 737 |
|
| 738 | 738 |
req.runConfig.StopSignal = sig |
| 739 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("STOPSIGNAL %v", req.args))
|
|
| 739 |
+ return req.builder.commit(fmt.Sprintf("STOPSIGNAL %v", req.args))
|
|
| 740 | 740 |
} |
| 741 | 741 |
|
| 742 | 742 |
// ARG name[=value] |
| ... | ... |
@@ -786,7 +779,7 @@ func arg(req dispatchRequest) error {
|
| 786 | 786 |
req.builder.buildArgs.AddMetaArg(name, value) |
| 787 | 787 |
return nil |
| 788 | 788 |
} |
| 789 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("ARG %s", arg))
|
|
| 789 |
+ return req.builder.commit("ARG " + arg)
|
|
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 | 792 |
// SHELL powershell -command |
| ... | ... |
@@ -808,7 +801,7 @@ func shell(req dispatchRequest) error {
|
| 808 | 808 |
// SHELL powershell -command - not JSON |
| 809 | 809 |
return errNotJSON("SHELL", req.original)
|
| 810 | 810 |
} |
| 811 |
- return req.builder.commit("", req.runConfig.Cmd, fmt.Sprintf("SHELL %v", shellSlice))
|
|
| 811 |
+ return req.builder.commit(fmt.Sprintf("SHELL %v", shellSlice))
|
|
| 812 | 812 |
} |
| 813 | 813 |
|
| 814 | 814 |
func errAtLeastOneArgument(command string) error {
|
| ... | ... |
@@ -831,15 +824,6 @@ func errTooManyArguments(command string) error {
|
| 831 | 831 |
return fmt.Errorf("Bad input to %s, too many arguments", command)
|
| 832 | 832 |
} |
| 833 | 833 |
|
| 834 |
-// getShell is a helper function which gets the right shell for prefixing the |
|
| 835 |
-// shell-form of RUN, ENTRYPOINT and CMD instructions |
|
| 836 |
-func getShell(c *container.Config) []string {
|
|
| 837 |
- if 0 == len(c.Shell) {
|
|
| 838 |
- return append([]string{}, defaultShell[:]...)
|
|
| 839 |
- } |
|
| 840 |
- return append([]string{}, c.Shell[:]...)
|
|
| 841 |
-} |
|
| 842 |
- |
|
| 843 | 834 |
// mountByRef creates an imageMount from a reference. pulling the image if needed. |
| 844 | 835 |
func mountByRef(b *Builder, name string) (*imageMount, error) {
|
| 845 | 836 |
image, err := pullOrGetImage(b, name) |
| ... | ... |
@@ -36,41 +36,39 @@ import ( |
| 36 | 36 |
"github.com/pkg/errors" |
| 37 | 37 |
) |
| 38 | 38 |
|
| 39 |
-func (b *Builder) commit(id string, autoCmd strslice.StrSlice, comment string) error {
|
|
| 39 |
+func (b *Builder) commit(comment string) error {
|
|
| 40 | 40 |
if b.disableCommit {
|
| 41 | 41 |
return nil |
| 42 | 42 |
} |
| 43 | 43 |
if !b.hasFromImage() {
|
| 44 | 44 |
return errors.New("Please provide a source image with `from` prior to commit")
|
| 45 | 45 |
} |
| 46 |
+ // TODO: why is this set here? |
|
| 46 | 47 |
b.runConfig.Image = b.image |
| 47 | 48 |
|
| 48 |
- if id == "" {
|
|
| 49 |
- cmd := b.runConfig.Cmd |
|
| 50 |
- b.runConfig.Cmd = strslice.StrSlice(append(getShell(b.runConfig), "#(nop) ", comment)) |
|
| 51 |
- defer func(cmd strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
|
|
| 52 |
- |
|
| 53 |
- hit, err := b.probeCache() |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return err |
|
| 56 |
- } else if hit {
|
|
| 57 |
- return nil |
|
| 58 |
- } |
|
| 59 |
- id, err = b.create() |
|
| 60 |
- if err != nil {
|
|
| 61 |
- return err |
|
| 62 |
- } |
|
| 49 |
+ runConfigWithCommentCmd := copyRunConfig(b.runConfig, withCmdComment(comment)) |
|
| 50 |
+ hit, err := b.probeCache(b.image, runConfigWithCommentCmd) |
|
| 51 |
+ if err != nil || hit {
|
|
| 52 |
+ return err |
|
| 53 |
+ } |
|
| 54 |
+ id, err := b.create(runConfigWithCommentCmd) |
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ return err |
|
| 63 | 57 |
} |
| 64 | 58 |
|
| 65 |
- // Note: Actually copy the struct |
|
| 66 |
- autoConfig := *b.runConfig |
|
| 67 |
- autoConfig.Cmd = autoCmd |
|
| 59 |
+ return b.commitContainer(id, b.runConfig) |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func (b *Builder) commitContainer(id string, runConfig *container.Config) error {
|
|
| 63 |
+ if b.disableCommit {
|
|
| 64 |
+ return nil |
|
| 65 |
+ } |
|
| 68 | 66 |
|
| 69 | 67 |
commitCfg := &backend.ContainerCommitConfig{
|
| 70 | 68 |
ContainerCommitConfig: types.ContainerCommitConfig{
|
| 71 | 69 |
Author: b.maintainer, |
| 72 | 70 |
Pause: true, |
| 73 |
- Config: &autoConfig, |
|
| 71 |
+ Config: runConfig, |
|
| 74 | 72 |
}, |
| 75 | 73 |
} |
| 76 | 74 |
|
| ... | ... |
@@ -80,8 +78,10 @@ func (b *Builder) commit(id string, autoCmd strslice.StrSlice, comment string) e |
| 80 | 80 |
return err |
| 81 | 81 |
} |
| 82 | 82 |
|
| 83 |
+ // TODO: this function should return imageID and runConfig instead of setting |
|
| 84 |
+ // then on the builder |
|
| 83 | 85 |
b.image = imageID |
| 84 |
- b.imageContexts.update(imageID, &autoConfig) |
|
| 86 |
+ b.imageContexts.update(imageID, runConfig) |
|
| 85 | 87 |
return nil |
| 86 | 88 |
} |
| 87 | 89 |
|
| ... | ... |
@@ -148,11 +148,9 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 148 | 148 |
// For backwards compat, if there's just one info then use it as the |
| 149 | 149 |
// cache look-up string, otherwise hash 'em all into one |
| 150 | 150 |
var srcHash string |
| 151 |
- var origPaths string |
|
| 152 | 151 |
|
| 153 | 152 |
if len(infos) == 1 {
|
| 154 | 153 |
info := infos[0] |
| 155 |
- origPaths = info.path |
|
| 156 | 154 |
srcHash = info.hash |
| 157 | 155 |
} else {
|
| 158 | 156 |
var hashs []string |
| ... | ... |
@@ -164,17 +162,16 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 164 | 164 |
hasher := sha256.New() |
| 165 | 165 |
hasher.Write([]byte(strings.Join(hashs, ","))) |
| 166 | 166 |
srcHash = "multi:" + hex.EncodeToString(hasher.Sum(nil)) |
| 167 |
- origPaths = strings.Join(origs, " ") |
|
| 168 | 167 |
} |
| 169 | 168 |
|
| 170 | 169 |
cmd := b.runConfig.Cmd |
| 170 |
+ // TODO: should this have been using origPaths instead of srcHash in the comment? |
|
| 171 | 171 |
b.runConfig.Cmd = strslice.StrSlice(append(getShell(b.runConfig), fmt.Sprintf("#(nop) %s %s in %s ", cmdName, srcHash, dest)))
|
| 172 | 172 |
defer func(cmd strslice.StrSlice) { b.runConfig.Cmd = cmd }(cmd)
|
| 173 | 173 |
|
| 174 |
- if hit, err := b.probeCache(); err != nil {
|
|
| 174 |
+ // TODO: this should pass a copy of runConfig |
|
| 175 |
+ if hit, err := b.probeCache(b.image, b.runConfig); err != nil || hit {
|
|
| 175 | 176 |
return err |
| 176 |
- } else if hit {
|
|
| 177 |
- return nil |
|
| 178 | 177 |
} |
| 179 | 178 |
|
| 180 | 179 |
container, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
|
| ... | ... |
@@ -187,8 +184,6 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 187 | 187 |
} |
| 188 | 188 |
b.tmpContainers[container.ID] = struct{}{}
|
| 189 | 189 |
|
| 190 |
- comment := fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest)
|
|
| 191 |
- |
|
| 192 | 190 |
// Twiddle the destination when it's a relative path - meaning, make it |
| 193 | 191 |
// relative to the WORKINGDIR |
| 194 | 192 |
if dest, err = normaliseDest(cmdName, b.runConfig.WorkingDir, dest); err != nil {
|
| ... | ... |
@@ -201,7 +196,44 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
| 201 | 201 |
} |
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 |
- return b.commit(container.ID, cmd, comment) |
|
| 204 |
+ return b.commitContainer(container.ID, copyRunConfig(b.runConfig, withCmd(cmd))) |
|
| 205 |
+} |
|
| 206 |
+ |
|
| 207 |
+type runConfigModifier func(*container.Config) |
|
| 208 |
+ |
|
| 209 |
+func copyRunConfig(runConfig *container.Config, modifiers ...runConfigModifier) *container.Config {
|
|
| 210 |
+ copy := *runConfig |
|
| 211 |
+ for _, modifier := range modifiers {
|
|
| 212 |
+ modifier(©) |
|
| 213 |
+ } |
|
| 214 |
+ return © |
|
| 215 |
+} |
|
| 216 |
+ |
|
| 217 |
+func withCmd(cmd []string) runConfigModifier {
|
|
| 218 |
+ return func(runConfig *container.Config) {
|
|
| 219 |
+ runConfig.Cmd = cmd |
|
| 220 |
+ } |
|
| 221 |
+} |
|
| 222 |
+ |
|
| 223 |
+func withCmdComment(comment string) runConfigModifier {
|
|
| 224 |
+ return func(runConfig *container.Config) {
|
|
| 225 |
+ runConfig.Cmd = append(getShell(runConfig), "#(nop) ", comment) |
|
| 226 |
+ } |
|
| 227 |
+} |
|
| 228 |
+ |
|
| 229 |
+func withEnv(env []string) runConfigModifier {
|
|
| 230 |
+ return func(runConfig *container.Config) {
|
|
| 231 |
+ runConfig.Env = env |
|
| 232 |
+ } |
|
| 233 |
+} |
|
| 234 |
+ |
|
| 235 |
+// getShell is a helper function which gets the right shell for prefixing the |
|
| 236 |
+// shell-form of RUN, ENTRYPOINT and CMD instructions |
|
| 237 |
+func getShell(c *container.Config) []string {
|
|
| 238 |
+ if 0 == len(c.Shell) {
|
|
| 239 |
+ return append([]string{}, defaultShell[:]...)
|
|
| 240 |
+ } |
|
| 241 |
+ return append([]string{}, c.Shell[:]...)
|
|
| 205 | 242 |
} |
| 206 | 243 |
|
| 207 | 244 |
func (b *Builder) download(srcURL string) (remote builder.Source, p string, err error) {
|
| ... | ... |
@@ -498,35 +530,33 @@ func (b *Builder) processImageFrom(img builder.Image) error {
|
| 498 | 498 |
// If an image is found, probeCache returns `(true, nil)`. |
| 499 | 499 |
// If no image is found, it returns `(false, nil)`. |
| 500 | 500 |
// If there is any error, it returns `(false, err)`. |
| 501 |
-func (b *Builder) probeCache() (bool, error) {
|
|
| 501 |
+func (b *Builder) probeCache(imageID string, runConfig *container.Config) (bool, error) {
|
|
| 502 | 502 |
c := b.imageCache |
| 503 | 503 |
if c == nil || b.options.NoCache || b.cacheBusted {
|
| 504 | 504 |
return false, nil |
| 505 | 505 |
} |
| 506 |
- cache, err := c.GetCache(b.image, b.runConfig) |
|
| 506 |
+ cache, err := c.GetCache(imageID, runConfig) |
|
| 507 | 507 |
if err != nil {
|
| 508 | 508 |
return false, err |
| 509 | 509 |
} |
| 510 | 510 |
if len(cache) == 0 {
|
| 511 |
- logrus.Debugf("[BUILDER] Cache miss: %s", b.runConfig.Cmd)
|
|
| 511 |
+ logrus.Debugf("[BUILDER] Cache miss: %s", runConfig.Cmd)
|
|
| 512 | 512 |
b.cacheBusted = true |
| 513 | 513 |
return false, nil |
| 514 | 514 |
} |
| 515 | 515 |
|
| 516 | 516 |
fmt.Fprint(b.Stdout, " ---> Using cache\n") |
| 517 |
- logrus.Debugf("[BUILDER] Use cached version: %s", b.runConfig.Cmd)
|
|
| 517 |
+ logrus.Debugf("[BUILDER] Use cached version: %s", runConfig.Cmd)
|
|
| 518 | 518 |
b.image = string(cache) |
| 519 |
- b.imageContexts.update(b.image, b.runConfig) |
|
| 519 |
+ b.imageContexts.update(b.image, runConfig) |
|
| 520 | 520 |
|
| 521 | 521 |
return true, nil |
| 522 | 522 |
} |
| 523 | 523 |
|
| 524 |
-func (b *Builder) create() (string, error) {
|
|
| 524 |
+func (b *Builder) create(runConfig *container.Config) (string, error) {
|
|
| 525 | 525 |
if !b.hasFromImage() {
|
| 526 | 526 |
return "", errors.New("Please provide a source image with `from` prior to run")
|
| 527 | 527 |
} |
| 528 |
- b.runConfig.Image = b.image |
|
| 529 |
- |
|
| 530 | 528 |
resources := container.Resources{
|
| 531 | 529 |
CgroupParent: b.options.CgroupParent, |
| 532 | 530 |
CPUShares: b.options.CPUShares, |
| ... | ... |
@@ -551,11 +581,9 @@ func (b *Builder) create() (string, error) {
|
| 551 | 551 |
ExtraHosts: b.options.ExtraHosts, |
| 552 | 552 |
} |
| 553 | 553 |
|
| 554 |
- config := *b.runConfig |
|
| 555 |
- |
|
| 556 | 554 |
// Create the container |
| 557 | 555 |
c, err := b.docker.ContainerCreate(types.ContainerCreateConfig{
|
| 558 |
- Config: b.runConfig, |
|
| 556 |
+ Config: runConfig, |
|
| 559 | 557 |
HostConfig: hostConfig, |
| 560 | 558 |
}) |
| 561 | 559 |
if err != nil {
|
| ... | ... |
@@ -569,7 +597,7 @@ func (b *Builder) create() (string, error) {
|
| 569 | 569 |
fmt.Fprintf(b.Stdout, " ---> Running in %s\n", stringid.TruncateID(c.ID)) |
| 570 | 570 |
|
| 571 | 571 |
// override the entry point that may have been picked up from the base image |
| 572 |
- if err := b.docker.ContainerUpdateCmdOnBuild(c.ID, config.Cmd); err != nil {
|
|
| 572 |
+ if err := b.docker.ContainerUpdateCmdOnBuild(c.ID, runConfig.Cmd); err != nil {
|
|
| 573 | 573 |
return "", err |
| 574 | 574 |
} |
| 575 | 575 |
|
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"fmt" |
| 6 | 6 |
"testing" |
| 7 | 7 |
|
| 8 |
+ "github.com/docker/docker/api/types/container" |
|
| 8 | 9 |
"github.com/docker/docker/builder" |
| 9 | 10 |
"github.com/docker/docker/builder/remotecontext" |
| 10 | 11 |
"github.com/docker/docker/pkg/archive" |
| ... | ... |
@@ -71,3 +72,54 @@ func readAndCheckDockerfile(t *testing.T, testName, contextDir, dockerfilePath, |
| 71 | 71 |
_, _, err = remotecontext.Detect(context.Background(), "", dockerfilePath, tarStream, nil) |
| 72 | 72 |
assert.EqualError(t, err, expectedError) |
| 73 | 73 |
} |
| 74 |
+ |
|
| 75 |
+func TestCopyRunConfig(t *testing.T) {
|
|
| 76 |
+ defaultEnv := []string{"foo=1"}
|
|
| 77 |
+ defaultCmd := []string{"old"}
|
|
| 78 |
+ |
|
| 79 |
+ var testcases = []struct {
|
|
| 80 |
+ doc string |
|
| 81 |
+ modifiers []runConfigModifier |
|
| 82 |
+ expected *container.Config |
|
| 83 |
+ }{
|
|
| 84 |
+ {
|
|
| 85 |
+ doc: "Set the command", |
|
| 86 |
+ modifiers: []runConfigModifier{withCmd([]string{"new"})},
|
|
| 87 |
+ expected: &container.Config{
|
|
| 88 |
+ Cmd: []string{"new"},
|
|
| 89 |
+ Env: defaultEnv, |
|
| 90 |
+ }, |
|
| 91 |
+ }, |
|
| 92 |
+ {
|
|
| 93 |
+ doc: "Set the command to a comment", |
|
| 94 |
+ modifiers: []runConfigModifier{withCmdComment("comment")},
|
|
| 95 |
+ expected: &container.Config{
|
|
| 96 |
+ Cmd: append(defaultShell, "#(nop) ", "comment"), |
|
| 97 |
+ Env: defaultEnv, |
|
| 98 |
+ }, |
|
| 99 |
+ }, |
|
| 100 |
+ {
|
|
| 101 |
+ doc: "Set the command and env", |
|
| 102 |
+ modifiers: []runConfigModifier{
|
|
| 103 |
+ withCmd([]string{"new"}),
|
|
| 104 |
+ withEnv([]string{"one", "two"}),
|
|
| 105 |
+ }, |
|
| 106 |
+ expected: &container.Config{
|
|
| 107 |
+ Cmd: []string{"new"},
|
|
| 108 |
+ Env: []string{"one", "two"},
|
|
| 109 |
+ }, |
|
| 110 |
+ }, |
|
| 111 |
+ } |
|
| 112 |
+ |
|
| 113 |
+ for _, testcase := range testcases {
|
|
| 114 |
+ runConfig := &container.Config{
|
|
| 115 |
+ Cmd: defaultCmd, |
|
| 116 |
+ Env: defaultEnv, |
|
| 117 |
+ } |
|
| 118 |
+ runConfigCopy := copyRunConfig(runConfig, testcase.modifiers...) |
|
| 119 |
+ assert.Equal(t, testcase.expected, runConfigCopy, testcase.doc) |
|
| 120 |
+ // Assert the original was not modified |
|
| 121 |
+ assert.NotEqual(t, runConfig, runConfigCopy, testcase.doc) |
|
| 122 |
+ } |
|
| 123 |
+ |
|
| 124 |
+} |