Docker-DCO-1.1-Signed-off-by: Erik Hollensbe <github@hollensbe.org> (github: erikh)
Erik Hollensbe authored on 2014/10/14 05:14:35... | ... |
@@ -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") |