github.com/akerouanton/docker@v1.11.0-rc3/integration-cli/docker_api_build_test.go (about)

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