github.com/damirazo/docker@v1.9.0/integration-cli/docker_api_build_test.go (about) 1 package main 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "net/http" 7 "strings" 8 9 "github.com/go-check/check" 10 ) 11 12 func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) { 13 // Test to make sure we stop people from trying to leave the 14 // build context when specifying the path to the dockerfile 15 buffer := new(bytes.Buffer) 16 tw := tar.NewWriter(buffer) 17 defer tw.Close() 18 19 dockerfile := []byte("FROM busybox") 20 if err := tw.WriteHeader(&tar.Header{ 21 Name: "Dockerfile", 22 Size: int64(len(dockerfile)), 23 }); err != nil { 24 c.Fatalf("failed to write tar file header: %v", err) 25 } 26 if _, err := tw.Write(dockerfile); err != nil { 27 c.Fatalf("failed to write tar file content: %v", err) 28 } 29 if err := tw.Close(); err != nil { 30 c.Fatalf("failed to close tar archive: %v", err) 31 } 32 33 res, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar") 34 c.Assert(err, check.IsNil) 35 c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError) 36 37 out, err := readBody(body) 38 if err != nil { 39 c.Fatal(err) 40 } 41 42 if !strings.Contains(string(out), "Forbidden path outside the build context") { 43 c.Fatalf("Didn't complain about leaving build context: %s", out) 44 } 45 } 46 47 func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) { 48 testRequires(c, NotUserNamespace) 49 testRequires(c, DaemonIsLinux) 50 server, err := fakeStorage(map[string]string{ 51 "testD": `FROM busybox 52 COPY * /tmp/ 53 RUN find / -name ba* 54 RUN find /tmp/`, 55 }) 56 if err != nil { 57 c.Fatal(err) 58 } 59 defer server.Close() 60 61 res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json") 62 c.Assert(err, check.IsNil) 63 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 64 65 buf, err := readBody(body) 66 if err != nil { 67 c.Fatal(err) 68 } 69 70 // Make sure Dockerfile exists. 71 // Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL 72 out := string(buf) 73 if !strings.Contains(out, "/tmp/Dockerfile") || 74 strings.Contains(out, "baz") { 75 c.Fatalf("Incorrect output: %s", out) 76 } 77 } 78 79 func (s *DockerSuite) TestBuildApiRemoteTarballContext(c *check.C) { 80 testRequires(c, DaemonIsLinux) 81 buffer := new(bytes.Buffer) 82 tw := tar.NewWriter(buffer) 83 defer tw.Close() 84 85 dockerfile := []byte("FROM busybox") 86 if err := tw.WriteHeader(&tar.Header{ 87 Name: "Dockerfile", 88 Size: int64(len(dockerfile)), 89 }); err != nil { 90 c.Fatalf("failed to write tar file header: %v", err) 91 } 92 if _, err := tw.Write(dockerfile); err != nil { 93 c.Fatalf("failed to write tar file content: %v", err) 94 } 95 if err := tw.Close(); err != nil { 96 c.Fatalf("failed to close tar archive: %v", err) 97 } 98 99 server, err := fakeBinaryStorage(map[string]*bytes.Buffer{ 100 "testT.tar": buffer, 101 }) 102 c.Assert(err, check.IsNil) 103 104 defer server.Close() 105 106 res, b, err := sockRequestRaw("POST", "/build?remote="+server.URL()+"/testT.tar", nil, "application/tar") 107 c.Assert(err, check.IsNil) 108 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 109 b.Close() 110 } 111 112 func (s *DockerSuite) TestBuildApiRemoteTarballContextWithCustomDockerfile(c *check.C) { 113 testRequires(c, DaemonIsLinux) 114 buffer := new(bytes.Buffer) 115 tw := tar.NewWriter(buffer) 116 defer tw.Close() 117 118 dockerfile := []byte(`FROM busybox 119 RUN echo 'wrong'`) 120 if err := tw.WriteHeader(&tar.Header{ 121 Name: "Dockerfile", 122 Size: int64(len(dockerfile)), 123 }); err != nil { 124 c.Fatalf("failed to write tar file header: %v", err) 125 } 126 if _, err := tw.Write(dockerfile); err != nil { 127 c.Fatalf("failed to write tar file content: %v", err) 128 } 129 130 custom := []byte(`FROM busybox 131 RUN echo 'right' 132 `) 133 if err := tw.WriteHeader(&tar.Header{ 134 Name: "custom", 135 Size: int64(len(custom)), 136 }); err != nil { 137 c.Fatalf("failed to write tar file header: %v", err) 138 } 139 if _, err := tw.Write(custom); err != nil { 140 c.Fatalf("failed to write tar file content: %v", err) 141 } 142 143 if err := tw.Close(); err != nil { 144 c.Fatalf("failed to close tar archive: %v", err) 145 } 146 147 server, err := fakeBinaryStorage(map[string]*bytes.Buffer{ 148 "testT.tar": buffer, 149 }) 150 c.Assert(err, check.IsNil) 151 152 defer server.Close() 153 url := "/build?dockerfile=custom&remote=" + server.URL() + "/testT.tar" 154 res, body, err := sockRequestRaw("POST", url, nil, "application/tar") 155 c.Assert(err, check.IsNil) 156 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 157 158 defer body.Close() 159 content, err := readBody(body) 160 c.Assert(err, check.IsNil) 161 162 if strings.Contains(string(content), "wrong") { 163 c.Fatalf("Build used the wrong dockerfile.") 164 } 165 } 166 167 func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) { 168 testRequires(c, DaemonIsLinux) 169 git, err := newFakeGit("repo", map[string]string{ 170 "dockerfile": `FROM busybox 171 RUN echo from dockerfile`, 172 }, false) 173 if err != nil { 174 c.Fatal(err) 175 } 176 defer git.Close() 177 178 res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json") 179 c.Assert(err, check.IsNil) 180 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 181 182 buf, err := readBody(body) 183 if err != nil { 184 c.Fatal(err) 185 } 186 187 out := string(buf) 188 if !strings.Contains(out, "from dockerfile") { 189 c.Fatalf("Incorrect output: %s", out) 190 } 191 } 192 193 func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) { 194 testRequires(c, DaemonIsLinux) 195 git, err := newFakeGit("repo", map[string]string{ 196 "baz": `FROM busybox 197 RUN echo from baz`, 198 "Dockerfile": `FROM busybox 199 RUN echo from Dockerfile`, 200 }, false) 201 if err != nil { 202 c.Fatal(err) 203 } 204 defer git.Close() 205 206 // Make sure it tries to 'dockerfile' query param value 207 res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json") 208 c.Assert(err, check.IsNil) 209 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 210 211 buf, err := readBody(body) 212 if err != nil { 213 c.Fatal(err) 214 } 215 216 out := string(buf) 217 if !strings.Contains(out, "from baz") { 218 c.Fatalf("Incorrect output: %s", out) 219 } 220 } 221 222 func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) { 223 testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows 224 git, err := newFakeGit("repo", map[string]string{ 225 "Dockerfile": `FROM busybox 226 RUN echo from Dockerfile`, 227 "dockerfile": `FROM busybox 228 RUN echo from dockerfile`, 229 }, false) 230 if err != nil { 231 c.Fatal(err) 232 } 233 defer git.Close() 234 235 // Make sure it tries to 'dockerfile' query param value 236 res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json") 237 c.Assert(err, check.IsNil) 238 c.Assert(res.StatusCode, check.Equals, http.StatusOK) 239 240 buf, err := readBody(body) 241 if err != nil { 242 c.Fatal(err) 243 } 244 245 out := string(buf) 246 if !strings.Contains(out, "from Dockerfile") { 247 c.Fatalf("Incorrect output: %s", out) 248 } 249 } 250 251 func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) { 252 // Test to make sure we stop people from trying to leave the 253 // build context when specifying a symlink as the path to the dockerfile 254 buffer := new(bytes.Buffer) 255 tw := tar.NewWriter(buffer) 256 defer tw.Close() 257 258 if err := tw.WriteHeader(&tar.Header{ 259 Name: "Dockerfile", 260 Typeflag: tar.TypeSymlink, 261 Linkname: "/etc/passwd", 262 }); err != nil { 263 c.Fatalf("failed to write tar file header: %v", err) 264 } 265 if err := tw.Close(); err != nil { 266 c.Fatalf("failed to close tar archive: %v", err) 267 } 268 269 res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar") 270 c.Assert(err, check.IsNil) 271 c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError) 272 273 out, err := readBody(body) 274 if err != nil { 275 c.Fatal(err) 276 } 277 278 // The reason the error is "Cannot locate specified Dockerfile" is because 279 // in the builder, the symlink is resolved within the context, therefore 280 // Dockerfile -> /etc/passwd becomes etc/passwd from the context which is 281 // a nonexistent file. 282 if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") { 283 c.Fatalf("Didn't complain about leaving build context: %s", out) 284 } 285 }