Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
| ... | ... |
@@ -20,7 +20,7 @@ import ( |
| 20 | 20 |
) |
| 21 | 21 |
|
| 22 | 22 |
// dispatch with no layer / parsing. This is effectively not a command. |
| 23 |
-func nullDispatch(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 23 |
+func nullDispatch(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 24 | 24 |
return nil |
| 25 | 25 |
} |
| 26 | 26 |
|
| ... | ... |
@@ -29,7 +29,7 @@ func nullDispatch(b *Builder, args []string, attributes map[string]bool) error {
|
| 29 | 29 |
// Sets the environment variable foo to bar, also makes interpolation |
| 30 | 30 |
// in the dockerfile available from the next statement on via ${foo}.
|
| 31 | 31 |
// |
| 32 |
-func env(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 32 |
+func env(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 33 | 33 |
if len(args) != 2 {
|
| 34 | 34 |
return fmt.Errorf("ENV accepts two arguments")
|
| 35 | 35 |
} |
| ... | ... |
@@ -50,7 +50,7 @@ func env(b *Builder, args []string, attributes map[string]bool) error {
|
| 50 | 50 |
// MAINTAINER some text <maybe@an.email.address> |
| 51 | 51 |
// |
| 52 | 52 |
// Sets the maintainer metadata. |
| 53 |
-func maintainer(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 53 |
+func maintainer(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 54 | 54 |
if len(args) != 1 {
|
| 55 | 55 |
return fmt.Errorf("MAINTAINER requires only one argument")
|
| 56 | 56 |
} |
| ... | ... |
@@ -64,7 +64,7 @@ func maintainer(b *Builder, args []string, attributes map[string]bool) error {
|
| 64 | 64 |
// Add the file 'foo' to '/path'. Tarball and Remote URL (git, http) handling |
| 65 | 65 |
// exist here. If you do not wish to have this automatic handling, use COPY. |
| 66 | 66 |
// |
| 67 |
-func add(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 67 |
+func add(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 68 | 68 |
if len(args) < 2 {
|
| 69 | 69 |
return fmt.Errorf("ADD requires at least two arguments")
|
| 70 | 70 |
} |
| ... | ... |
@@ -76,7 +76,7 @@ func add(b *Builder, args []string, attributes map[string]bool) error {
|
| 76 | 76 |
// |
| 77 | 77 |
// Same as 'ADD' but without the tar and remote url handling. |
| 78 | 78 |
// |
| 79 |
-func dispatchCopy(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 79 |
+func dispatchCopy(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 80 | 80 |
if len(args) < 2 {
|
| 81 | 81 |
return fmt.Errorf("COPY requires at least two arguments")
|
| 82 | 82 |
} |
| ... | ... |
@@ -88,7 +88,7 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool) error {
|
| 88 | 88 |
// |
| 89 | 89 |
// This sets the image the dockerfile will build on top of. |
| 90 | 90 |
// |
| 91 |
-func from(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 91 |
+func from(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 92 | 92 |
if len(args) != 1 {
|
| 93 | 93 |
return fmt.Errorf("FROM requires one argument")
|
| 94 | 94 |
} |
| ... | ... |
@@ -120,7 +120,7 @@ func from(b *Builder, args []string, attributes map[string]bool) error {
|
| 120 | 120 |
// special cases. search for 'OnBuild' in internals.go for additional special |
| 121 | 121 |
// cases. |
| 122 | 122 |
// |
| 123 |
-func onbuild(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 123 |
+func onbuild(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 124 | 124 |
triggerInstruction := strings.ToUpper(strings.TrimSpace(args[0])) |
| 125 | 125 |
switch triggerInstruction {
|
| 126 | 126 |
case "ONBUILD": |
| ... | ... |
@@ -129,17 +129,17 @@ func onbuild(b *Builder, args []string, attributes map[string]bool) error {
|
| 129 | 129 |
return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", triggerInstruction)
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 |
- trigger := strings.Join(args, " ") |
|
| 132 |
+ original = strings.TrimSpace(strings.TrimLeft(original, "ONBUILD")) |
|
| 133 | 133 |
|
| 134 |
- b.Config.OnBuild = append(b.Config.OnBuild, trigger) |
|
| 135 |
- return b.commit("", b.Config.Cmd, fmt.Sprintf("ONBUILD %s", trigger))
|
|
| 134 |
+ b.Config.OnBuild = append(b.Config.OnBuild, original) |
|
| 135 |
+ return b.commit("", b.Config.Cmd, fmt.Sprintf("ONBUILD %s", original))
|
|
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 | 138 |
// WORKDIR /tmp |
| 139 | 139 |
// |
| 140 | 140 |
// Set the working directory for future RUN/CMD/etc statements. |
| 141 | 141 |
// |
| 142 |
-func workdir(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 142 |
+func workdir(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 143 | 143 |
if len(args) != 1 {
|
| 144 | 144 |
return fmt.Errorf("WORKDIR requires exactly one argument")
|
| 145 | 145 |
} |
| ... | ... |
@@ -167,7 +167,7 @@ func workdir(b *Builder, args []string, attributes map[string]bool) error {
|
| 167 | 167 |
// RUN echo hi # sh -c echo hi |
| 168 | 168 |
// RUN [ "echo", "hi" ] # echo hi |
| 169 | 169 |
// |
| 170 |
-func run(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 170 |
+func run(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 171 | 171 |
if b.image == "" {
|
| 172 | 172 |
return fmt.Errorf("Please provide a source image with `from` prior to run")
|
| 173 | 173 |
} |
| ... | ... |
@@ -230,7 +230,7 @@ func run(b *Builder, args []string, attributes map[string]bool) error {
|
| 230 | 230 |
// Set the default command to run in the container (which may be empty). |
| 231 | 231 |
// Argument handling is the same as RUN. |
| 232 | 232 |
// |
| 233 |
-func cmd(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 233 |
+func cmd(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 234 | 234 |
b.Config.Cmd = handleJsonArgs(args, attributes) |
| 235 | 235 |
|
| 236 | 236 |
if !attributes["json"] && len(b.Config.Entrypoint) == 0 {
|
| ... | ... |
@@ -256,7 +256,7 @@ func cmd(b *Builder, args []string, attributes map[string]bool) error {
|
| 256 | 256 |
// Handles command processing similar to CMD and RUN, only b.Config.Entrypoint |
| 257 | 257 |
// is initialized at NewBuilder time instead of through argument parsing. |
| 258 | 258 |
// |
| 259 |
-func entrypoint(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 259 |
+func entrypoint(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 260 | 260 |
parsed := handleJsonArgs(args, attributes) |
| 261 | 261 |
|
| 262 | 262 |
switch {
|
| ... | ... |
@@ -289,7 +289,7 @@ func entrypoint(b *Builder, args []string, attributes map[string]bool) error {
|
| 289 | 289 |
// Expose ports for links and port mappings. This all ends up in |
| 290 | 290 |
// b.Config.ExposedPorts for runconfig. |
| 291 | 291 |
// |
| 292 |
-func expose(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 292 |
+func expose(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 293 | 293 |
portsTab := args |
| 294 | 294 |
|
| 295 | 295 |
if b.Config.ExposedPorts == nil {
|
| ... | ... |
@@ -316,7 +316,7 @@ func expose(b *Builder, args []string, attributes map[string]bool) error {
|
| 316 | 316 |
// Set the user to 'foo' for future commands and when running the |
| 317 | 317 |
// ENTRYPOINT/CMD at container run time. |
| 318 | 318 |
// |
| 319 |
-func user(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 319 |
+func user(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 320 | 320 |
if len(args) != 1 {
|
| 321 | 321 |
return fmt.Errorf("USER requires exactly one argument")
|
| 322 | 322 |
} |
| ... | ... |
@@ -329,7 +329,7 @@ func user(b *Builder, args []string, attributes map[string]bool) error {
|
| 329 | 329 |
// |
| 330 | 330 |
// Expose the volume /foo for use. Will also accept the JSON array form. |
| 331 | 331 |
// |
| 332 |
-func volume(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 332 |
+func volume(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 333 | 333 |
if len(args) == 0 {
|
| 334 | 334 |
return fmt.Errorf("Volume cannot be empty")
|
| 335 | 335 |
} |
| ... | ... |
@@ -347,6 +347,6 @@ func volume(b *Builder, args []string, attributes map[string]bool) error {
|
| 347 | 347 |
} |
| 348 | 348 |
|
| 349 | 349 |
// INSERT is no longer accepted, but we still parse it. |
| 350 |
-func insert(b *Builder, args []string, attributes map[string]bool) error {
|
|
| 350 |
+func insert(b *Builder, args []string, attributes map[string]bool, original string) error {
|
|
| 351 | 351 |
return fmt.Errorf("INSERT has been deprecated. Please use ADD instead")
|
| 352 | 352 |
} |
| ... | ... |
@@ -41,10 +41,10 @@ var ( |
| 41 | 41 |
ErrDockerfileEmpty = errors.New("Dockerfile cannot be empty")
|
| 42 | 42 |
) |
| 43 | 43 |
|
| 44 |
-var evaluateTable map[string]func(*Builder, []string, map[string]bool) error |
|
| 44 |
+var evaluateTable map[string]func(*Builder, []string, map[string]bool, string) error |
|
| 45 | 45 |
|
| 46 | 46 |
func init() {
|
| 47 |
- evaluateTable = map[string]func(*Builder, []string, map[string]bool) error{
|
|
| 47 |
+ evaluateTable = map[string]func(*Builder, []string, map[string]bool, string) error{
|
|
| 48 | 48 |
"env": env, |
| 49 | 49 |
"maintainer": maintainer, |
| 50 | 50 |
"add": add, |
| ... | ... |
@@ -190,6 +190,7 @@ func (b *Builder) Run(context io.Reader) (string, error) {
|
| 190 | 190 |
func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
| 191 | 191 |
cmd := ast.Value |
| 192 | 192 |
attrs := ast.Attributes |
| 193 |
+ original := ast.Original |
|
| 193 | 194 |
strs := []string{}
|
| 194 | 195 |
msg := fmt.Sprintf("Step %d : %s", stepN, strings.ToUpper(cmd))
|
| 195 | 196 |
|
| ... | ... |
@@ -210,7 +211,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
|
| 210 | 210 |
// XXX yes, we skip any cmds that are not valid; the parser should have |
| 211 | 211 |
// picked these out already. |
| 212 | 212 |
if f, ok := evaluateTable[cmd]; ok {
|
| 213 |
- return f(b, strs, attrs) |
|
| 213 |
+ return f(b, strs, attrs, original) |
|
| 214 | 214 |
} |
| 215 | 215 |
|
| 216 | 216 |
fmt.Fprintf(b.ErrStream, "# Skipping unknown instruction %s\n", strings.ToUpper(cmd)) |
| ... | ... |
@@ -18,6 +18,7 @@ import ( |
| 18 | 18 |
"syscall" |
| 19 | 19 |
"time" |
| 20 | 20 |
|
| 21 |
+ "github.com/docker/docker/builder/parser" |
|
| 21 | 22 |
"github.com/docker/docker/daemon" |
| 22 | 23 |
imagepkg "github.com/docker/docker/image" |
| 23 | 24 |
"github.com/docker/docker/pkg/archive" |
| ... | ... |
@@ -436,30 +437,26 @@ func (b *Builder) processImageFrom(img *imagepkg.Image) error {
|
| 436 | 436 |
onBuildTriggers := b.Config.OnBuild |
| 437 | 437 |
b.Config.OnBuild = []string{}
|
| 438 | 438 |
|
| 439 |
- // FIXME rewrite this so that builder/parser is used; right now steps in |
|
| 440 |
- // onbuild are muted because we have no good way to represent the step |
|
| 441 |
- // number |
|
| 439 |
+ // parse the ONBUILD triggers by invoking the parser |
|
| 442 | 440 |
for stepN, step := range onBuildTriggers {
|
| 443 |
- splitStep := strings.Split(step, " ") |
|
| 444 |
- stepInstruction := strings.ToUpper(strings.Trim(splitStep[0], " ")) |
|
| 445 |
- switch stepInstruction {
|
|
| 446 |
- case "ONBUILD": |
|
| 447 |
- return fmt.Errorf("Source image contains forbidden chained `ONBUILD ONBUILD` trigger: %s", step)
|
|
| 448 |
- case "MAINTAINER", "FROM": |
|
| 449 |
- return fmt.Errorf("Source image contains forbidden %s trigger: %s", stepInstruction, step)
|
|
| 441 |
+ ast, err := parser.Parse(strings.NewReader(step)) |
|
| 442 |
+ if err != nil {
|
|
| 443 |
+ return err |
|
| 450 | 444 |
} |
| 451 | 445 |
|
| 452 |
- // FIXME we have to run the evaluator manually here. This does not belong |
|
| 453 |
- // in this function. Once removed, the init() in evaluator.go should no |
|
| 454 |
- // longer be necessary. |
|
| 446 |
+ for i, n := range ast.Children {
|
|
| 447 |
+ switch strings.ToUpper(n.Value) {
|
|
| 448 |
+ case "ONBUILD": |
|
| 449 |
+ return fmt.Errorf("Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed")
|
|
| 450 |
+ case "MAINTAINER", "FROM": |
|
| 451 |
+ return fmt.Errorf("%s isn't allowed as an ONBUILD trigger", n.Value)
|
|
| 452 |
+ } |
|
| 455 | 453 |
|
| 456 |
- if f, ok := evaluateTable[strings.ToLower(stepInstruction)]; ok {
|
|
| 457 | 454 |
fmt.Fprintf(b.OutStream, "Trigger %d, %s\n", stepN, step) |
| 458 |
- if err := f(b, splitStep[1:], nil); err != nil {
|
|
| 455 |
+ |
|
| 456 |
+ if err := b.dispatch(i, n); err != nil {
|
|
| 459 | 457 |
return err |
| 460 | 458 |
} |
| 461 |
- } else {
|
|
| 462 |
- return fmt.Errorf("%s doesn't appear to be a valid Dockerfile instruction", splitStep[0])
|
|
| 463 | 459 |
} |
| 464 | 460 |
} |
| 465 | 461 |
|
| ... | ... |
@@ -26,6 +26,7 @@ type Node struct {
|
| 26 | 26 |
Next *Node // the next item in the current sexp |
| 27 | 27 |
Children []*Node // the children of this sexp |
| 28 | 28 |
Attributes map[string]bool // special attributes for this node |
| 29 |
+ Original string // original line used before parsing |
|
| 29 | 30 |
} |
| 30 | 31 |
|
| 31 | 32 |
var ( |
| ... | ... |
@@ -84,6 +85,7 @@ func parseLine(line string) (string, *Node, error) {
|
| 84 | 84 |
if sexp.Value != "" || sexp.Next != nil || sexp.Children != nil {
|
| 85 | 85 |
node.Next = sexp |
| 86 | 86 |
node.Attributes = attrs |
| 87 |
+ node.Original = line |
|
| 87 | 88 |
} |
| 88 | 89 |
|
| 89 | 90 |
return "", node, nil |
| ... | ... |
@@ -7,6 +7,7 @@ import ( |
| 7 | 7 |
"os" |
| 8 | 8 |
"os/exec" |
| 9 | 9 |
"path/filepath" |
| 10 |
+ "regexp" |
|
| 10 | 11 |
"strings" |
| 11 | 12 |
"testing" |
| 12 | 13 |
"time" |
| ... | ... |
@@ -14,6 +15,165 @@ import ( |
| 14 | 14 |
"github.com/docker/docker/pkg/archive" |
| 15 | 15 |
) |
| 16 | 16 |
|
| 17 |
+func TestBuildOnBuildForbiddenMaintainerInSourceImage(t *testing.T) {
|
|
| 18 |
+ name := "testbuildonbuildforbiddenmaintainerinsourceimage" |
|
| 19 |
+ defer deleteImages(name) |
|
| 20 |
+ createCmd := exec.Command(dockerBinary, "create", "busybox", "true") |
|
| 21 |
+ out, _, _, err := runCommandWithStdoutStderr(createCmd) |
|
| 22 |
+ errorOut(err, t, out) |
|
| 23 |
+ |
|
| 24 |
+ cleanedContainerID := stripTrailingCharacters(out) |
|
| 25 |
+ |
|
| 26 |
+ commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"MAINTAINER docker.io\"]}", cleanedContainerID, "onbuild")
|
|
| 27 |
+ |
|
| 28 |
+ if _, err := runCommand(commitCmd); err != nil {
|
|
| 29 |
+ t.Fatal(err) |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ _, err = buildImage(name, |
|
| 33 |
+ `FROM onbuild`, |
|
| 34 |
+ true) |
|
| 35 |
+ if err != nil {
|
|
| 36 |
+ if !strings.Contains(err.Error(), "maintainer isn't allowed as an ONBUILD trigger") {
|
|
| 37 |
+ t.Fatalf("Wrong error %v, must be about MAINTAINER and ONBUILD in source image", err)
|
|
| 38 |
+ } |
|
| 39 |
+ } else {
|
|
| 40 |
+ t.Fatal("Error must not be nil")
|
|
| 41 |
+ } |
|
| 42 |
+ logDone("build - onbuild forbidden maintainer in source image")
|
|
| 43 |
+ |
|
| 44 |
+} |
|
| 45 |
+ |
|
| 46 |
+func TestBuildOnBuildForbiddenFromInSourceImage(t *testing.T) {
|
|
| 47 |
+ name := "testbuildonbuildforbiddenfrominsourceimage" |
|
| 48 |
+ defer deleteImages(name) |
|
| 49 |
+ createCmd := exec.Command(dockerBinary, "create", "busybox", "true") |
|
| 50 |
+ out, _, _, err := runCommandWithStdoutStderr(createCmd) |
|
| 51 |
+ errorOut(err, t, out) |
|
| 52 |
+ |
|
| 53 |
+ cleanedContainerID := stripTrailingCharacters(out) |
|
| 54 |
+ |
|
| 55 |
+ commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"FROM busybox\"]}", cleanedContainerID, "onbuild")
|
|
| 56 |
+ |
|
| 57 |
+ if _, err := runCommand(commitCmd); err != nil {
|
|
| 58 |
+ t.Fatal(err) |
|
| 59 |
+ } |
|
| 60 |
+ |
|
| 61 |
+ _, err = buildImage(name, |
|
| 62 |
+ `FROM onbuild`, |
|
| 63 |
+ true) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ if !strings.Contains(err.Error(), "from isn't allowed as an ONBUILD trigger") {
|
|
| 66 |
+ t.Fatalf("Wrong error %v, must be about FROM and ONBUILD in source image", err)
|
|
| 67 |
+ } |
|
| 68 |
+ } else {
|
|
| 69 |
+ t.Fatal("Error must not be nil")
|
|
| 70 |
+ } |
|
| 71 |
+ logDone("build - onbuild forbidden from in source image")
|
|
| 72 |
+ |
|
| 73 |
+} |
|
| 74 |
+ |
|
| 75 |
+func TestBuildOnBuildForbiddenChainedInSourceImage(t *testing.T) {
|
|
| 76 |
+ name := "testbuildonbuildforbiddenchainedinsourceimage" |
|
| 77 |
+ defer deleteImages(name) |
|
| 78 |
+ createCmd := exec.Command(dockerBinary, "create", "busybox", "true") |
|
| 79 |
+ out, _, _, err := runCommandWithStdoutStderr(createCmd) |
|
| 80 |
+ errorOut(err, t, out) |
|
| 81 |
+ |
|
| 82 |
+ cleanedContainerID := stripTrailingCharacters(out) |
|
| 83 |
+ |
|
| 84 |
+ commitCmd := exec.Command(dockerBinary, "commit", "--run", "{\"OnBuild\":[\"ONBUILD RUN ls\"]}", cleanedContainerID, "onbuild")
|
|
| 85 |
+ |
|
| 86 |
+ if _, err := runCommand(commitCmd); err != nil {
|
|
| 87 |
+ t.Fatal(err) |
|
| 88 |
+ } |
|
| 89 |
+ |
|
| 90 |
+ _, err = buildImage(name, |
|
| 91 |
+ `FROM onbuild`, |
|
| 92 |
+ true) |
|
| 93 |
+ if err != nil {
|
|
| 94 |
+ if !strings.Contains(err.Error(), "Chaining ONBUILD via `ONBUILD ONBUILD` isn't allowed") {
|
|
| 95 |
+ t.Fatalf("Wrong error %v, must be about chaining ONBUILD in source image", err)
|
|
| 96 |
+ } |
|
| 97 |
+ } else {
|
|
| 98 |
+ t.Fatal("Error must not be nil")
|
|
| 99 |
+ } |
|
| 100 |
+ logDone("build - onbuild forbidden chained in source image")
|
|
| 101 |
+ |
|
| 102 |
+} |
|
| 103 |
+ |
|
| 104 |
+func TestBuildOnBuildCmdEntrypointJSON(t *testing.T) {
|
|
| 105 |
+ name1 := "onbuildcmd" |
|
| 106 |
+ name2 := "onbuildgenerated" |
|
| 107 |
+ |
|
| 108 |
+ defer deleteAllContainers() |
|
| 109 |
+ defer deleteImages(name2) |
|
| 110 |
+ defer deleteImages(name1) |
|
| 111 |
+ |
|
| 112 |
+ _, err := buildImage(name1, ` |
|
| 113 |
+FROM busybox |
|
| 114 |
+ONBUILD CMD ["hello world"] |
|
| 115 |
+ONBUILD ENTRYPOINT ["echo"] |
|
| 116 |
+ONBUILD RUN ["true"]`, |
|
| 117 |
+ false) |
|
| 118 |
+ |
|
| 119 |
+ if err != nil {
|
|
| 120 |
+ t.Fatal(err) |
|
| 121 |
+ } |
|
| 122 |
+ |
|
| 123 |
+ _, err = buildImage(name2, fmt.Sprintf(`FROM %s`, name1), false) |
|
| 124 |
+ |
|
| 125 |
+ if err != nil {
|
|
| 126 |
+ t.Fatal(err) |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2)) |
|
| 130 |
+ if err != nil {
|
|
| 131 |
+ t.Fatal(err) |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
|
|
| 135 |
+ t.Fatal("did not get echo output from onbuild", out)
|
|
| 136 |
+ } |
|
| 137 |
+ |
|
| 138 |
+ logDone("build - onbuild with json entrypoint/cmd")
|
|
| 139 |
+} |
|
| 140 |
+ |
|
| 141 |
+func TestBuildOnBuildEntrypointJSON(t *testing.T) {
|
|
| 142 |
+ name1 := "onbuildcmd" |
|
| 143 |
+ name2 := "onbuildgenerated" |
|
| 144 |
+ |
|
| 145 |
+ defer deleteAllContainers() |
|
| 146 |
+ defer deleteImages(name2) |
|
| 147 |
+ defer deleteImages(name1) |
|
| 148 |
+ |
|
| 149 |
+ _, err := buildImage(name1, ` |
|
| 150 |
+FROM busybox |
|
| 151 |
+ONBUILD ENTRYPOINT ["echo"]`, |
|
| 152 |
+ false) |
|
| 153 |
+ |
|
| 154 |
+ if err != nil {
|
|
| 155 |
+ t.Fatal(err) |
|
| 156 |
+ } |
|
| 157 |
+ |
|
| 158 |
+ _, err = buildImage(name2, fmt.Sprintf("FROM %s\nCMD [\"hello world\"]\n", name1), false)
|
|
| 159 |
+ |
|
| 160 |
+ if err != nil {
|
|
| 161 |
+ t.Fatal(err) |
|
| 162 |
+ } |
|
| 163 |
+ |
|
| 164 |
+ out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-t", name2)) |
|
| 165 |
+ if err != nil {
|
|
| 166 |
+ t.Fatal(err) |
|
| 167 |
+ } |
|
| 168 |
+ |
|
| 169 |
+ if !regexp.MustCompile(`(?m)^hello world`).MatchString(out) {
|
|
| 170 |
+ t.Fatal("got malformed output from onbuild", out)
|
|
| 171 |
+ } |
|
| 172 |
+ |
|
| 173 |
+ logDone("build - onbuild with json entrypoint")
|
|
| 174 |
+} |
|
| 175 |
+ |
|
| 17 | 176 |
func TestBuildCacheADD(t *testing.T) {
|
| 18 | 177 |
name := "testbuildtwoimageswithadd" |
| 19 | 178 |
defer deleteImages(name) |
| ... | ... |
@@ -2386,8 +2546,8 @@ func TestBuildOnBuildOutput(t *testing.T) {
|
| 2386 | 2386 |
t.Fatal(err) |
| 2387 | 2387 |
} |
| 2388 | 2388 |
|
| 2389 |
- if !strings.Contains(out, "Trigger 0, run echo foo") {
|
|
| 2390 |
- t.Fatal("failed to find the ONBUILD output")
|
|
| 2389 |
+ if !strings.Contains(out, "Trigger 0, RUN echo foo") {
|
|
| 2390 |
+ t.Fatal("failed to find the ONBUILD output", out)
|
|
| 2391 | 2391 |
} |
| 2392 | 2392 |
|
| 2393 | 2393 |
logDone("build - onbuild output")
|