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