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