Fix dockerfile parser with empty line after escape
| ... | ... |
@@ -176,10 +176,17 @@ func Parse(rwc io.Reader, d *Directive) (*Node, error) {
|
| 176 | 176 |
newline := scanner.Text() |
| 177 | 177 |
currentLine++ |
| 178 | 178 |
|
| 179 |
- if stripComments(strings.TrimSpace(newline)) == "" {
|
|
| 180 |
- continue |
|
| 179 |
+ // If escape followed by a comment line then stop |
|
| 180 |
+ // Note here that comment line starts with `#` at |
|
| 181 |
+ // the first pos of the line |
|
| 182 |
+ if stripComments(newline) == "" {
|
|
| 183 |
+ break |
|
| 181 | 184 |
} |
| 182 | 185 |
|
| 186 |
+ // If escape followed by an empty line then stop |
|
| 187 |
+ if strings.TrimSpace(newline) == "" {
|
|
| 188 |
+ break |
|
| 189 |
+ } |
|
| 183 | 190 |
line, child, err = ParseLine(line+newline, d) |
| 184 | 191 |
if err != nil {
|
| 185 | 192 |
return nil, err |
| ... | ... |
@@ -150,8 +150,8 @@ func TestLineInformation(t *testing.T) {
|
| 150 | 150 |
t.Fatalf("Error parsing dockerfile %s: %v", testFileLineInfo, err)
|
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 |
- if ast.StartLine != 5 || ast.EndLine != 31 {
|
|
| 154 |
- fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 31, ast.StartLine, ast.EndLine) |
|
| 153 |
+ if ast.StartLine != 5 || ast.EndLine != 27 {
|
|
| 154 |
+ fmt.Fprintf(os.Stderr, "Wrong root line information: expected(%d-%d), actual(%d-%d)\n", 5, 27, ast.StartLine, ast.EndLine) |
|
| 155 | 155 |
t.Fatalf("Root line information doesn't match result.")
|
| 156 | 156 |
} |
| 157 | 157 |
if len(ast.Children) != 3 {
|
| ... | ... |
@@ -161,7 +161,7 @@ func TestLineInformation(t *testing.T) {
|
| 161 | 161 |
expected := [][]int{
|
| 162 | 162 |
{5, 5},
|
| 163 | 163 |
{11, 12},
|
| 164 |
- {17, 31},
|
|
| 164 |
+ {17, 27},
|
|
| 165 | 165 |
} |
| 166 | 166 |
for i, child := range ast.Children {
|
| 167 | 167 |
if child.StartLine != expected[i][0] || child.EndLine != expected[i][1] {
|
| ... | ... |
@@ -16,15 +16,11 @@ ENV GOPATH \ |
| 16 | 16 |
# Install the packages we need, clean up after them and us |
| 17 | 17 |
RUN apt-get update \ |
| 18 | 18 |
&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.clean \
|
| 19 |
- |
|
| 20 |
- |
|
| 21 | 19 |
&& apt-get install -y --no-install-recommends git golang ca-certificates \ |
| 22 | 20 |
&& apt-get clean \ |
| 23 | 21 |
&& rm -rf /var/lib/apt/lists \ |
| 24 |
- |
|
| 25 | 22 |
&& go get -v github.com/brimstone/consuldock \ |
| 26 | 23 |
&& mv $GOPATH/bin/consuldock /usr/local/bin/consuldock \ |
| 27 |
- |
|
| 28 | 24 |
&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \
|
| 29 | 25 |
&& apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \
|
| 30 | 26 |
&& rm /tmp/dpkg.* \ |
| ... | ... |
@@ -16,10 +16,8 @@ RUN apt-get update \ |
| 16 | 16 |
&& apt-get install -y --no-install-recommends git golang ca-certificates \ |
| 17 | 17 |
&& apt-get clean \ |
| 18 | 18 |
&& rm -rf /var/lib/apt/lists \ |
| 19 |
- |
|
| 20 | 19 |
&& go get -v github.com/brimstone/consuldock \ |
| 21 | 20 |
&& mv $GOPATH/bin/consuldock /usr/local/bin/consuldock \ |
| 22 |
- |
|
| 23 | 21 |
&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \
|
| 24 | 22 |
&& apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \
|
| 25 | 23 |
&& rm /tmp/dpkg.* \ |
| ... | ... |
@@ -23,14 +23,12 @@ RUN apt-get update \ |
| 23 | 23 |
&& apt-get install -y --no-install-recommends unzip wget \ |
| 24 | 24 |
&& apt-get clean \ |
| 25 | 25 |
&& rm -rf /var/lib/apt/lists \ |
| 26 |
- |
|
| 27 | 26 |
&& cd /tmp \ |
| 28 | 27 |
&& wget https://dl.bintray.com/mitchellh/consul/0.3.1_web_ui.zip \ |
| 29 | 28 |
-O web_ui.zip \ |
| 30 | 29 |
&& unzip web_ui.zip \ |
| 31 | 30 |
&& mv dist /webui \ |
| 32 | 31 |
&& rm web_ui.zip \ |
| 33 |
- |
|
| 34 | 32 |
&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \
|
| 35 | 33 |
&& apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \
|
| 36 | 34 |
&& rm /tmp/dpkg.* |
| ... | ... |
@@ -42,10 +40,8 @@ RUN apt-get update \ |
| 42 | 42 |
&& apt-get install -y --no-install-recommends git golang ca-certificates build-essential \ |
| 43 | 43 |
&& apt-get clean \ |
| 44 | 44 |
&& rm -rf /var/lib/apt/lists \ |
| 45 |
- |
|
| 46 | 45 |
&& go get -v github.com/hashicorp/consul \ |
| 47 | 46 |
&& mv $GOPATH/bin/consul /usr/bin/consul \ |
| 48 |
- |
|
| 49 | 47 |
&& dpkg -l | awk '/^ii/ {print $2}' > /tmp/dpkg.dirty \
|
| 50 | 48 |
&& apt-get remove --purge -y $(diff /tmp/dpkg.clean /tmp/dpkg.dirty | awk '/^>/ {print $2}') \
|
| 51 | 49 |
&& rm /tmp/dpkg.* \ |
| 10 | 11 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,15 @@ |
| 0 |
+FROM busybox |
|
| 1 |
+ |
|
| 2 |
+# The following will create two instructions |
|
| 3 |
+# `Run foo` |
|
| 4 |
+# `bar` |
|
| 5 |
+# because empty line will break the escape. |
|
| 6 |
+# The parser will generate the following: |
|
| 7 |
+# (from "busybox") |
|
| 8 |
+# (run "foo") |
|
| 9 |
+# (bar "") |
|
| 10 |
+# And `bar` will return an error instruction later |
|
| 11 |
+# Note: Parse() will not immediately error out. |
|
| 12 |
+RUN foo \ |
|
| 13 |
+ |
|
| 14 |
+bar |
| ... | ... |
@@ -3610,8 +3610,8 @@ RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '1001:1001/do |
| 3610 | 3610 |
|
| 3611 | 3611 |
# Switch back to root and double check that worked exactly as we might expect it to |
| 3612 | 3612 |
USER root |
| 3613 |
+# Add a "supplementary" group for our dockerio user |
|
| 3613 | 3614 |
RUN [ "$(id -u):$(id -g)/$(id -un):$(id -gn)/$(id -G):$(id -Gn)" = '0:0/root:root/0 10:root wheel' ] && \ |
| 3614 |
- # Add a "supplementary" group for our dockerio user \ |
|
| 3615 | 3615 |
echo 'supplementary:x:1002:dockerio' >> /etc/group |
| 3616 | 3616 |
|
| 3617 | 3617 |
# ... and then go verify that we get it like we expect |
| ... | ... |
@@ -7139,3 +7139,38 @@ func (s *DockerSuite) TestBuildNetContainer(c *check.C) {
|
| 7139 | 7139 |
host, _ := dockerCmd(c, "run", "testbuildnetcontainer", "cat", "/otherhost") |
| 7140 | 7140 |
c.Assert(strings.TrimSpace(host), check.Equals, "foobar") |
| 7141 | 7141 |
} |
| 7142 |
+ |
|
| 7143 |
+// Test case for #24693 |
|
| 7144 |
+func (s *DockerSuite) TestBuildRunEmptyLineAfterEscape(c *check.C) {
|
|
| 7145 |
+ name := "testbuildemptylineafterescape" |
|
| 7146 |
+ _, out, err := buildImageWithOut(name, |
|
| 7147 |
+ ` |
|
| 7148 |
+FROM busybox |
|
| 7149 |
+RUN echo x \ |
|
| 7150 |
+ |
|
| 7151 |
+RUN echo y |
|
| 7152 |
+RUN echo z |
|
| 7153 |
+# Comment requires the '#' to start from position 1 |
|
| 7154 |
+# RUN echo w |
|
| 7155 |
+`, true) |
|
| 7156 |
+ c.Assert(err, checker.IsNil) |
|
| 7157 |
+ c.Assert(out, checker.Contains, "Step 1/4 : FROM busybox") |
|
| 7158 |
+ c.Assert(out, checker.Contains, "Step 2/4 : RUN echo x") |
|
| 7159 |
+ c.Assert(out, checker.Contains, "Step 3/4 : RUN echo y") |
|
| 7160 |
+ c.Assert(out, checker.Contains, "Step 4/4 : RUN echo z") |
|
| 7161 |
+ |
|
| 7162 |
+ // With comment, see #24693 |
|
| 7163 |
+ name = "testbuildcommentandemptylineafterescape" |
|
| 7164 |
+ _, out, err = buildImageWithOut(name, |
|
| 7165 |
+ ` |
|
| 7166 |
+FROM busybox |
|
| 7167 |
+RUN echo grafana && \ |
|
| 7168 |
+ echo raintank \ |
|
| 7169 |
+#echo env-load |
|
| 7170 |
+RUN echo vegeta |
|
| 7171 |
+`, true) |
|
| 7172 |
+ c.Assert(err, checker.IsNil) |
|
| 7173 |
+ c.Assert(out, checker.Contains, "Step 1/3 : FROM busybox") |
|
| 7174 |
+ c.Assert(out, checker.Contains, "Step 2/3 : RUN echo grafana && echo raintank") |
|
| 7175 |
+ c.Assert(out, checker.Contains, "Step 3/3 : RUN echo vegeta") |
|
| 7176 |
+} |