github.com/ld86/docker@v1.7.1-rc3/integration-cli/docker_api_containers_test.go (about)

     1  package main
     2  
     3  import (
     4  	"archive/tar"
     5  	"bytes"
     6  	"encoding/json"
     7  	"io"
     8  	"net/http"
     9  	"net/http/httputil"
    10  	"os"
    11  	"os/exec"
    12  	"strconv"
    13  	"strings"
    14  	"time"
    15  
    16  	"github.com/docker/docker/api/types"
    17  	"github.com/docker/docker/pkg/stringid"
    18  	"github.com/docker/docker/runconfig"
    19  	"github.com/go-check/check"
    20  )
    21  
    22  func (s *DockerSuite) TestContainerApiGetAll(c *check.C) {
    23  	startCount, err := getContainerCount()
    24  	if err != nil {
    25  		c.Fatalf("Cannot query container count: %v", err)
    26  	}
    27  
    28  	name := "getall"
    29  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "true")
    30  	out, _, err := runCommandWithOutput(runCmd)
    31  	if err != nil {
    32  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
    33  	}
    34  
    35  	status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
    36  	c.Assert(status, check.Equals, http.StatusOK)
    37  	c.Assert(err, check.IsNil)
    38  
    39  	var inspectJSON []struct {
    40  		Names []string
    41  	}
    42  	if err = json.Unmarshal(body, &inspectJSON); err != nil {
    43  		c.Fatalf("unable to unmarshal response body: %v", err)
    44  	}
    45  
    46  	if len(inspectJSON) != startCount+1 {
    47  		c.Fatalf("Expected %d container(s), %d found (started with: %d)", startCount+1, len(inspectJSON), startCount)
    48  	}
    49  
    50  	if actual := inspectJSON[0].Names[0]; actual != "/"+name {
    51  		c.Fatalf("Container Name mismatch. Expected: %q, received: %q\n", "/"+name, actual)
    52  	}
    53  }
    54  
    55  // regression test for empty json field being omitted #13691
    56  func (s *DockerSuite) TestContainerApiGetJSONNoFieldsOmitted(c *check.C) {
    57  	runCmd := exec.Command(dockerBinary, "run", "busybox", "true")
    58  	_, err := runCommand(runCmd)
    59  	c.Assert(err, check.IsNil)
    60  
    61  	status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
    62  	c.Assert(status, check.Equals, http.StatusOK)
    63  	c.Assert(err, check.IsNil)
    64  
    65  	// empty Labels field triggered this bug, make sense to check for everything
    66  	// cause even Ports for instance can trigger this bug
    67  	// better safe than sorry..
    68  	fields := []string{
    69  		"Id",
    70  		"Names",
    71  		"Image",
    72  		"Command",
    73  		"Created",
    74  		"Ports",
    75  		"Labels",
    76  		"Status",
    77  	}
    78  
    79  	// decoding into types.Container do not work since it eventually unmarshal
    80  	// and empty field to an empty go map, so we just check for a string
    81  	for _, f := range fields {
    82  		if !strings.Contains(string(body), f) {
    83  			c.Fatalf("Field %s is missing and it shouldn't", f)
    84  		}
    85  	}
    86  }
    87  
    88  type containerPs struct {
    89  	Names []string
    90  	Ports []map[string]interface{}
    91  }
    92  
    93  // regression test for non-empty fields from #13901
    94  func (s *DockerSuite) TestContainerPsOmitFields(c *check.C) {
    95  	name := "pstest"
    96  	port := 80
    97  	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", name, "--expose", strconv.Itoa(port), "busybox", "sleep", "5")
    98  	_, err := runCommand(runCmd)
    99  	c.Assert(err, check.IsNil)
   100  
   101  	status, body, err := sockRequest("GET", "/containers/json?all=1", nil)
   102  	c.Assert(status, check.Equals, http.StatusOK)
   103  	c.Assert(err, check.IsNil)
   104  
   105  	var resp []containerPs
   106  	err = json.Unmarshal(body, &resp)
   107  	c.Assert(err, check.IsNil)
   108  
   109  	var foundContainer *containerPs
   110  	for _, container := range resp {
   111  		for _, testName := range container.Names {
   112  			if "/"+name == testName {
   113  				foundContainer = &container
   114  				break
   115  			}
   116  		}
   117  	}
   118  
   119  	c.Assert(len(foundContainer.Ports), check.Equals, 1)
   120  	c.Assert(foundContainer.Ports[0]["PrivatePort"], check.Equals, float64(port))
   121  	_, ok := foundContainer.Ports[0]["PublicPort"]
   122  	c.Assert(ok, check.Not(check.Equals), true)
   123  	_, ok = foundContainer.Ports[0]["IP"]
   124  	c.Assert(ok, check.Not(check.Equals), true)
   125  }
   126  
   127  func (s *DockerSuite) TestContainerApiGetExport(c *check.C) {
   128  	name := "exportcontainer"
   129  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test")
   130  	out, _, err := runCommandWithOutput(runCmd)
   131  	if err != nil {
   132  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
   133  	}
   134  
   135  	status, body, err := sockRequest("GET", "/containers/"+name+"/export", nil)
   136  	c.Assert(status, check.Equals, http.StatusOK)
   137  	c.Assert(err, check.IsNil)
   138  
   139  	found := false
   140  	for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
   141  		h, err := tarReader.Next()
   142  		if err != nil {
   143  			if err == io.EOF {
   144  				break
   145  			}
   146  			c.Fatal(err)
   147  		}
   148  		if h.Name == "test" {
   149  			found = true
   150  			break
   151  		}
   152  	}
   153  
   154  	if !found {
   155  		c.Fatalf("The created test file has not been found in the exported image")
   156  	}
   157  }
   158  
   159  func (s *DockerSuite) TestContainerApiGetChanges(c *check.C) {
   160  	name := "changescontainer"
   161  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "rm", "/etc/passwd")
   162  	out, _, err := runCommandWithOutput(runCmd)
   163  	if err != nil {
   164  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
   165  	}
   166  
   167  	status, body, err := sockRequest("GET", "/containers/"+name+"/changes", nil)
   168  	c.Assert(status, check.Equals, http.StatusOK)
   169  	c.Assert(err, check.IsNil)
   170  
   171  	changes := []struct {
   172  		Kind int
   173  		Path string
   174  	}{}
   175  	if err = json.Unmarshal(body, &changes); err != nil {
   176  		c.Fatalf("unable to unmarshal response body: %v", err)
   177  	}
   178  
   179  	// Check the changelog for removal of /etc/passwd
   180  	success := false
   181  	for _, elem := range changes {
   182  		if elem.Path == "/etc/passwd" && elem.Kind == 2 {
   183  			success = true
   184  		}
   185  	}
   186  	if !success {
   187  		c.Fatalf("/etc/passwd has been removed but is not present in the diff")
   188  	}
   189  }
   190  
   191  func (s *DockerSuite) TestContainerApiStartVolumeBinds(c *check.C) {
   192  	name := "testing"
   193  	config := map[string]interface{}{
   194  		"Image":   "busybox",
   195  		"Volumes": map[string]struct{}{"/tmp": {}},
   196  	}
   197  
   198  	status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
   199  	c.Assert(status, check.Equals, http.StatusCreated)
   200  	c.Assert(err, check.IsNil)
   201  
   202  	bindPath := randomUnixTmpDirPath("test")
   203  	config = map[string]interface{}{
   204  		"Binds": []string{bindPath + ":/tmp"},
   205  	}
   206  	status, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
   207  	c.Assert(status, check.Equals, http.StatusNoContent)
   208  	c.Assert(err, check.IsNil)
   209  
   210  	pth, err := inspectFieldMap(name, "Volumes", "/tmp")
   211  	if err != nil {
   212  		c.Fatal(err)
   213  	}
   214  
   215  	if pth != bindPath {
   216  		c.Fatalf("expected volume host path to be %s, got %s", bindPath, pth)
   217  	}
   218  }
   219  
   220  // Test for GH#10618
   221  func (s *DockerSuite) TestContainerApiStartDupVolumeBinds(c *check.C) {
   222  	name := "testdups"
   223  	config := map[string]interface{}{
   224  		"Image":   "busybox",
   225  		"Volumes": map[string]struct{}{"/tmp": {}},
   226  	}
   227  
   228  	status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
   229  	c.Assert(status, check.Equals, http.StatusCreated)
   230  	c.Assert(err, check.IsNil)
   231  
   232  	bindPath1 := randomUnixTmpDirPath("test1")
   233  	bindPath2 := randomUnixTmpDirPath("test2")
   234  
   235  	config = map[string]interface{}{
   236  		"Binds": []string{bindPath1 + ":/tmp", bindPath2 + ":/tmp"},
   237  	}
   238  	status, body, err := sockRequest("POST", "/containers/"+name+"/start", config)
   239  	c.Assert(status, check.Equals, http.StatusInternalServerError)
   240  	c.Assert(err, check.IsNil)
   241  
   242  	if !strings.Contains(string(body), "Duplicate bind") {
   243  		c.Fatalf("Expected failure due to duplicate bind mounts to same path, instead got: %q with error: %v", string(body), err)
   244  	}
   245  }
   246  
   247  func (s *DockerSuite) TestContainerApiStartVolumesFrom(c *check.C) {
   248  	volName := "voltst"
   249  	volPath := "/tmp"
   250  
   251  	if out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "run", "-d", "--name", volName, "-v", volPath, "busybox")); err != nil {
   252  		c.Fatal(out, err)
   253  	}
   254  
   255  	name := "TestContainerApiStartDupVolumeBinds"
   256  	config := map[string]interface{}{
   257  		"Image":   "busybox",
   258  		"Volumes": map[string]struct{}{volPath: {}},
   259  	}
   260  
   261  	status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
   262  	c.Assert(status, check.Equals, http.StatusCreated)
   263  	c.Assert(err, check.IsNil)
   264  
   265  	config = map[string]interface{}{
   266  		"VolumesFrom": []string{volName},
   267  	}
   268  	status, _, err = sockRequest("POST", "/containers/"+name+"/start", config)
   269  	c.Assert(status, check.Equals, http.StatusNoContent)
   270  	c.Assert(err, check.IsNil)
   271  
   272  	pth, err := inspectFieldMap(name, "Volumes", volPath)
   273  	if err != nil {
   274  		c.Fatal(err)
   275  	}
   276  	pth2, err := inspectFieldMap(volName, "Volumes", volPath)
   277  	if err != nil {
   278  		c.Fatal(err)
   279  	}
   280  
   281  	if pth != pth2 {
   282  		c.Fatalf("expected volume host path to be %s, got %s", pth, pth2)
   283  	}
   284  }
   285  
   286  func (s *DockerSuite) TestGetContainerStats(c *check.C) {
   287  	var (
   288  		name   = "statscontainer"
   289  		runCmd = exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "top")
   290  	)
   291  	out, _, err := runCommandWithOutput(runCmd)
   292  	if err != nil {
   293  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
   294  	}
   295  	type b struct {
   296  		status int
   297  		body   []byte
   298  		err    error
   299  	}
   300  	bc := make(chan b, 1)
   301  	go func() {
   302  		status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
   303  		bc <- b{status, body, err}
   304  	}()
   305  
   306  	// allow some time to stream the stats from the container
   307  	time.Sleep(4 * time.Second)
   308  	if _, err := runCommand(exec.Command(dockerBinary, "rm", "-f", name)); err != nil {
   309  		c.Fatal(err)
   310  	}
   311  
   312  	// collect the results from the stats stream or timeout and fail
   313  	// if the stream was not disconnected.
   314  	select {
   315  	case <-time.After(2 * time.Second):
   316  		c.Fatal("stream was not closed after container was removed")
   317  	case sr := <-bc:
   318  		c.Assert(sr.err, check.IsNil)
   319  		c.Assert(sr.status, check.Equals, http.StatusOK)
   320  
   321  		dec := json.NewDecoder(bytes.NewBuffer(sr.body))
   322  		var s *types.Stats
   323  		// decode only one object from the stream
   324  		if err := dec.Decode(&s); err != nil {
   325  			c.Fatal(err)
   326  		}
   327  	}
   328  }
   329  
   330  func (s *DockerSuite) TestGetContainerStatsRmRunning(c *check.C) {
   331  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
   332  	id := strings.TrimSpace(out)
   333  
   334  	buf := &channelBuffer{make(chan []byte, 1)}
   335  	defer buf.Close()
   336  	chErr := make(chan error)
   337  	go func() {
   338  		_, body, err := sockRequestRaw("GET", "/containers/"+id+"/stats?stream=1", nil, "application/json")
   339  		if err != nil {
   340  			chErr <- err
   341  		}
   342  		defer body.Close()
   343  		_, err = io.Copy(buf, body)
   344  		chErr <- err
   345  	}()
   346  	defer func() {
   347  		c.Assert(<-chErr, check.IsNil)
   348  	}()
   349  
   350  	b := make([]byte, 32)
   351  	// make sure we've got some stats
   352  	_, err := buf.ReadTimeout(b, 2*time.Second)
   353  	c.Assert(err, check.IsNil)
   354  
   355  	// Now remove without `-f` and make sure we are still pulling stats
   356  	_, err = runCommand(exec.Command(dockerBinary, "rm", id))
   357  	c.Assert(err, check.Not(check.IsNil), check.Commentf("rm should have failed but didn't"))
   358  	_, err = buf.ReadTimeout(b, 2*time.Second)
   359  	c.Assert(err, check.IsNil)
   360  	dockerCmd(c, "rm", "-f", id)
   361  
   362  	_, err = buf.ReadTimeout(b, 2*time.Second)
   363  	c.Assert(err, check.Not(check.IsNil))
   364  }
   365  
   366  // regression test for gh13421
   367  // previous test was just checking one stat entry so it didn't fail (stats with
   368  // stream false always return one stat)
   369  func (s *DockerSuite) TestGetContainerStatsStream(c *check.C) {
   370  	name := "statscontainer"
   371  	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "top")
   372  	_, err := runCommand(runCmd)
   373  	c.Assert(err, check.IsNil)
   374  
   375  	type b struct {
   376  		status int
   377  		body   []byte
   378  		err    error
   379  	}
   380  	bc := make(chan b, 1)
   381  	go func() {
   382  		status, body, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
   383  		bc <- b{status, body, err}
   384  	}()
   385  
   386  	// allow some time to stream the stats from the container
   387  	time.Sleep(4 * time.Second)
   388  	if _, err := runCommand(exec.Command(dockerBinary, "rm", "-f", name)); err != nil {
   389  		c.Fatal(err)
   390  	}
   391  
   392  	// collect the results from the stats stream or timeout and fail
   393  	// if the stream was not disconnected.
   394  	select {
   395  	case <-time.After(2 * time.Second):
   396  		c.Fatal("stream was not closed after container was removed")
   397  	case sr := <-bc:
   398  		c.Assert(sr.err, check.IsNil)
   399  		c.Assert(sr.status, check.Equals, http.StatusOK)
   400  
   401  		s := string(sr.body)
   402  		// count occurrences of "read" of types.Stats
   403  		if l := strings.Count(s, "read"); l < 2 {
   404  			c.Fatalf("Expected more than one stat streamed, got %d", l)
   405  		}
   406  	}
   407  }
   408  
   409  func (s *DockerSuite) TestGetContainerStatsNoStream(c *check.C) {
   410  	name := "statscontainer"
   411  	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", name, "busybox", "top")
   412  	_, err := runCommand(runCmd)
   413  	c.Assert(err, check.IsNil)
   414  
   415  	type b struct {
   416  		status int
   417  		body   []byte
   418  		err    error
   419  	}
   420  	bc := make(chan b, 1)
   421  	go func() {
   422  		status, body, err := sockRequest("GET", "/containers/"+name+"/stats?stream=0", nil)
   423  		bc <- b{status, body, err}
   424  	}()
   425  
   426  	// allow some time to stream the stats from the container
   427  	time.Sleep(4 * time.Second)
   428  	if _, err := runCommand(exec.Command(dockerBinary, "rm", "-f", name)); err != nil {
   429  		c.Fatal(err)
   430  	}
   431  
   432  	// collect the results from the stats stream or timeout and fail
   433  	// if the stream was not disconnected.
   434  	select {
   435  	case <-time.After(2 * time.Second):
   436  		c.Fatal("stream was not closed after container was removed")
   437  	case sr := <-bc:
   438  		c.Assert(sr.err, check.IsNil)
   439  		c.Assert(sr.status, check.Equals, http.StatusOK)
   440  
   441  		s := string(sr.body)
   442  		// count occurrences of "read" of types.Stats
   443  		if l := strings.Count(s, "read"); l != 1 {
   444  			c.Fatalf("Expected only one stat streamed, got %d", l)
   445  		}
   446  	}
   447  }
   448  
   449  func (s *DockerSuite) TestGetStoppedContainerStats(c *check.C) {
   450  	// TODO: this test does nothing because we are c.Assert'ing in goroutine
   451  	var (
   452  		name   = "statscontainer"
   453  		runCmd = exec.Command(dockerBinary, "create", "--name", name, "busybox", "top")
   454  	)
   455  	out, _, err := runCommandWithOutput(runCmd)
   456  	if err != nil {
   457  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
   458  	}
   459  
   460  	go func() {
   461  		// We'll never get return for GET stats from sockRequest as of now,
   462  		// just send request and see if panic or error would happen on daemon side.
   463  		status, _, err := sockRequest("GET", "/containers/"+name+"/stats", nil)
   464  		c.Assert(status, check.Equals, http.StatusOK)
   465  		c.Assert(err, check.IsNil)
   466  	}()
   467  
   468  	// allow some time to send request and let daemon deal with it
   469  	time.Sleep(1 * time.Second)
   470  }
   471  
   472  func (s *DockerSuite) TestBuildApiDockerfilePath(c *check.C) {
   473  	// Test to make sure we stop people from trying to leave the
   474  	// build context when specifying the path to the dockerfile
   475  	buffer := new(bytes.Buffer)
   476  	tw := tar.NewWriter(buffer)
   477  	defer tw.Close()
   478  
   479  	dockerfile := []byte("FROM busybox")
   480  	if err := tw.WriteHeader(&tar.Header{
   481  		Name: "Dockerfile",
   482  		Size: int64(len(dockerfile)),
   483  	}); err != nil {
   484  		c.Fatalf("failed to write tar file header: %v", err)
   485  	}
   486  	if _, err := tw.Write(dockerfile); err != nil {
   487  		c.Fatalf("failed to write tar file content: %v", err)
   488  	}
   489  	if err := tw.Close(); err != nil {
   490  		c.Fatalf("failed to close tar archive: %v", err)
   491  	}
   492  
   493  	res, body, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
   494  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
   495  	c.Assert(err, check.IsNil)
   496  
   497  	out, err := readBody(body)
   498  	if err != nil {
   499  		c.Fatal(err)
   500  	}
   501  
   502  	if !strings.Contains(string(out), "must be within the build context") {
   503  		c.Fatalf("Didn't complain about leaving build context: %s", out)
   504  	}
   505  }
   506  
   507  func (s *DockerSuite) TestBuildApiDockerFileRemote(c *check.C) {
   508  	server, err := fakeStorage(map[string]string{
   509  		"testD": `FROM busybox
   510  COPY * /tmp/
   511  RUN find / -name ba*
   512  RUN find /tmp/`,
   513  	})
   514  	if err != nil {
   515  		c.Fatal(err)
   516  	}
   517  	defer server.Close()
   518  
   519  	res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+server.URL()+"/testD", nil, "application/json")
   520  	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
   521  	c.Assert(err, check.IsNil)
   522  
   523  	buf, err := readBody(body)
   524  	if err != nil {
   525  		c.Fatal(err)
   526  	}
   527  
   528  	// Make sure Dockerfile exists.
   529  	// Make sure 'baz' doesn't exist ANYWHERE despite being mentioned in the URL
   530  	out := string(buf)
   531  	if !strings.Contains(out, "/tmp/Dockerfile") ||
   532  		strings.Contains(out, "baz") {
   533  		c.Fatalf("Incorrect output: %s", out)
   534  	}
   535  }
   536  
   537  func (s *DockerSuite) TestBuildApiLowerDockerfile(c *check.C) {
   538  	git, err := fakeGIT("repo", map[string]string{
   539  		"dockerfile": `FROM busybox
   540  RUN echo from dockerfile`,
   541  	}, false)
   542  	if err != nil {
   543  		c.Fatal(err)
   544  	}
   545  	defer git.Close()
   546  
   547  	res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
   548  	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
   549  	c.Assert(err, check.IsNil)
   550  
   551  	buf, err := readBody(body)
   552  	if err != nil {
   553  		c.Fatal(err)
   554  	}
   555  
   556  	out := string(buf)
   557  	if !strings.Contains(out, "from dockerfile") {
   558  		c.Fatalf("Incorrect output: %s", out)
   559  	}
   560  }
   561  
   562  func (s *DockerSuite) TestBuildApiBuildGitWithF(c *check.C) {
   563  	git, err := fakeGIT("repo", map[string]string{
   564  		"baz": `FROM busybox
   565  RUN echo from baz`,
   566  		"Dockerfile": `FROM busybox
   567  RUN echo from Dockerfile`,
   568  	}, false)
   569  	if err != nil {
   570  		c.Fatal(err)
   571  	}
   572  	defer git.Close()
   573  
   574  	// Make sure it tries to 'dockerfile' query param value
   575  	res, body, err := sockRequestRaw("POST", "/build?dockerfile=baz&remote="+git.RepoURL, nil, "application/json")
   576  	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
   577  	c.Assert(err, check.IsNil)
   578  
   579  	buf, err := readBody(body)
   580  	if err != nil {
   581  		c.Fatal(err)
   582  	}
   583  
   584  	out := string(buf)
   585  	if !strings.Contains(out, "from baz") {
   586  		c.Fatalf("Incorrect output: %s", out)
   587  	}
   588  }
   589  
   590  func (s *DockerSuite) TestBuildApiDoubleDockerfile(c *check.C) {
   591  	testRequires(c, UnixCli) // dockerfile overwrites Dockerfile on Windows
   592  	git, err := fakeGIT("repo", map[string]string{
   593  		"Dockerfile": `FROM busybox
   594  RUN echo from Dockerfile`,
   595  		"dockerfile": `FROM busybox
   596  RUN echo from dockerfile`,
   597  	}, false)
   598  	if err != nil {
   599  		c.Fatal(err)
   600  	}
   601  	defer git.Close()
   602  
   603  	// Make sure it tries to 'dockerfile' query param value
   604  	res, body, err := sockRequestRaw("POST", "/build?remote="+git.RepoURL, nil, "application/json")
   605  	c.Assert(res.StatusCode, check.Equals, http.StatusOK)
   606  	c.Assert(err, check.IsNil)
   607  
   608  	buf, err := readBody(body)
   609  	if err != nil {
   610  		c.Fatal(err)
   611  	}
   612  
   613  	out := string(buf)
   614  	if !strings.Contains(out, "from Dockerfile") {
   615  		c.Fatalf("Incorrect output: %s", out)
   616  	}
   617  }
   618  
   619  func (s *DockerSuite) TestBuildApiDockerfileSymlink(c *check.C) {
   620  	// Test to make sure we stop people from trying to leave the
   621  	// build context when specifying a symlink as the path to the dockerfile
   622  	buffer := new(bytes.Buffer)
   623  	tw := tar.NewWriter(buffer)
   624  	defer tw.Close()
   625  
   626  	if err := tw.WriteHeader(&tar.Header{
   627  		Name:     "Dockerfile",
   628  		Typeflag: tar.TypeSymlink,
   629  		Linkname: "/etc/passwd",
   630  	}); err != nil {
   631  		c.Fatalf("failed to write tar file header: %v", err)
   632  	}
   633  	if err := tw.Close(); err != nil {
   634  		c.Fatalf("failed to close tar archive: %v", err)
   635  	}
   636  
   637  	res, body, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
   638  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
   639  	c.Assert(err, check.IsNil)
   640  
   641  	out, err := readBody(body)
   642  	if err != nil {
   643  		c.Fatal(err)
   644  	}
   645  
   646  	// The reason the error is "Cannot locate specified Dockerfile" is because
   647  	// in the builder, the symlink is resolved within the context, therefore
   648  	// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
   649  	// a nonexistent file.
   650  	if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
   651  		c.Fatalf("Didn't complain about leaving build context: %s", out)
   652  	}
   653  }
   654  
   655  // #9981 - Allow a docker created volume (ie, one in /var/lib/docker/volumes) to be used to overwrite (via passing in Binds on api start) an existing volume
   656  func (s *DockerSuite) TestPostContainerBindNormalVolume(c *check.C) {
   657  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=one", "busybox"))
   658  	if err != nil {
   659  		c.Fatal(err, out)
   660  	}
   661  
   662  	fooDir, err := inspectFieldMap("one", "Volumes", "/foo")
   663  	if err != nil {
   664  		c.Fatal(err)
   665  	}
   666  
   667  	out, _, err = runCommandWithOutput(exec.Command(dockerBinary, "create", "-v", "/foo", "--name=two", "busybox"))
   668  	if err != nil {
   669  		c.Fatal(err, out)
   670  	}
   671  
   672  	bindSpec := map[string][]string{"Binds": {fooDir + ":/foo"}}
   673  	status, _, err := sockRequest("POST", "/containers/two/start", bindSpec)
   674  	c.Assert(status, check.Equals, http.StatusNoContent)
   675  	c.Assert(err, check.IsNil)
   676  
   677  	fooDir2, err := inspectFieldMap("two", "Volumes", "/foo")
   678  	if err != nil {
   679  		c.Fatal(err)
   680  	}
   681  
   682  	if fooDir2 != fooDir {
   683  		c.Fatalf("expected volume path to be %s, got: %s", fooDir, fooDir2)
   684  	}
   685  }
   686  
   687  func (s *DockerSuite) TestContainerApiPause(c *check.C) {
   688  	defer unpauseAllContainers()
   689  	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "sleep", "30")
   690  	out, _, err := runCommandWithOutput(runCmd)
   691  
   692  	if err != nil {
   693  		c.Fatalf("failed to create a container: %s, %v", out, err)
   694  	}
   695  	ContainerID := strings.TrimSpace(out)
   696  
   697  	status, _, err := sockRequest("POST", "/containers/"+ContainerID+"/pause", nil)
   698  	c.Assert(status, check.Equals, http.StatusNoContent)
   699  	c.Assert(err, check.IsNil)
   700  
   701  	pausedContainers, err := getSliceOfPausedContainers()
   702  
   703  	if err != nil {
   704  		c.Fatalf("error thrown while checking if containers were paused: %v", err)
   705  	}
   706  
   707  	if len(pausedContainers) != 1 || stringid.TruncateID(ContainerID) != pausedContainers[0] {
   708  		c.Fatalf("there should be one paused container and not %d", len(pausedContainers))
   709  	}
   710  
   711  	status, _, err = sockRequest("POST", "/containers/"+ContainerID+"/unpause", nil)
   712  	c.Assert(status, check.Equals, http.StatusNoContent)
   713  	c.Assert(err, check.IsNil)
   714  
   715  	pausedContainers, err = getSliceOfPausedContainers()
   716  
   717  	if err != nil {
   718  		c.Fatalf("error thrown while checking if containers were paused: %v", err)
   719  	}
   720  
   721  	if pausedContainers != nil {
   722  		c.Fatalf("There should be no paused container.")
   723  	}
   724  }
   725  
   726  func (s *DockerSuite) TestContainerApiTop(c *check.C) {
   727  	out, err := exec.Command(dockerBinary, "run", "-d", "busybox", "/bin/sh", "-c", "top").CombinedOutput()
   728  	if err != nil {
   729  		c.Fatal(err, out)
   730  	}
   731  	id := strings.TrimSpace(string(out))
   732  	if err := waitRun(id); err != nil {
   733  		c.Fatal(err)
   734  	}
   735  
   736  	type topResp struct {
   737  		Titles    []string
   738  		Processes [][]string
   739  	}
   740  	var top topResp
   741  	status, b, err := sockRequest("GET", "/containers/"+id+"/top?ps_args=aux", nil)
   742  	c.Assert(status, check.Equals, http.StatusOK)
   743  	c.Assert(err, check.IsNil)
   744  
   745  	if err := json.Unmarshal(b, &top); err != nil {
   746  		c.Fatal(err)
   747  	}
   748  
   749  	if len(top.Titles) != 11 {
   750  		c.Fatalf("expected 11 titles, found %d: %v", len(top.Titles), top.Titles)
   751  	}
   752  
   753  	if top.Titles[0] != "USER" || top.Titles[10] != "COMMAND" {
   754  		c.Fatalf("expected `USER` at `Titles[0]` and `COMMAND` at Titles[10]: %v", top.Titles)
   755  	}
   756  	if len(top.Processes) != 2 {
   757  		c.Fatalf("expected 2 processes, found %d: %v", len(top.Processes), top.Processes)
   758  	}
   759  	if top.Processes[0][10] != "/bin/sh -c top" {
   760  		c.Fatalf("expected `/bin/sh -c top`, found: %s", top.Processes[0][10])
   761  	}
   762  	if top.Processes[1][10] != "top" {
   763  		c.Fatalf("expected `top`, found: %s", top.Processes[1][10])
   764  	}
   765  }
   766  
   767  func (s *DockerSuite) TestContainerApiCommit(c *check.C) {
   768  	cName := "testapicommit"
   769  	out, err := exec.Command(dockerBinary, "run", "--name="+cName, "busybox", "/bin/sh", "-c", "touch /test").CombinedOutput()
   770  	if err != nil {
   771  		c.Fatal(err, out)
   772  	}
   773  
   774  	name := "TestContainerApiCommit"
   775  	status, b, err := sockRequest("POST", "/commit?repo="+name+"&testtag=tag&container="+cName, nil)
   776  	c.Assert(status, check.Equals, http.StatusCreated)
   777  	c.Assert(err, check.IsNil)
   778  
   779  	type resp struct {
   780  		Id string
   781  	}
   782  	var img resp
   783  	if err := json.Unmarshal(b, &img); err != nil {
   784  		c.Fatal(err)
   785  	}
   786  
   787  	cmd, err := inspectField(img.Id, "Config.Cmd")
   788  	if err != nil {
   789  		c.Fatal(err)
   790  	}
   791  	if cmd != "{[/bin/sh -c touch /test]}" {
   792  		c.Fatalf("got wrong Cmd from commit: %q", cmd)
   793  	}
   794  	// sanity check, make sure the image is what we think it is
   795  	out, err = exec.Command(dockerBinary, "run", img.Id, "ls", "/test").CombinedOutput()
   796  	if err != nil {
   797  		c.Fatalf("error checking committed image: %v - %q", err, string(out))
   798  	}
   799  }
   800  
   801  func (s *DockerSuite) TestContainerApiCreate(c *check.C) {
   802  	config := map[string]interface{}{
   803  		"Image": "busybox",
   804  		"Cmd":   []string{"/bin/sh", "-c", "touch /test && ls /test"},
   805  	}
   806  
   807  	status, b, err := sockRequest("POST", "/containers/create", config)
   808  	c.Assert(status, check.Equals, http.StatusCreated)
   809  	c.Assert(err, check.IsNil)
   810  
   811  	type createResp struct {
   812  		Id string
   813  	}
   814  	var container createResp
   815  	if err := json.Unmarshal(b, &container); err != nil {
   816  		c.Fatal(err)
   817  	}
   818  
   819  	out, err := exec.Command(dockerBinary, "start", "-a", container.Id).CombinedOutput()
   820  	if err != nil {
   821  		c.Fatal(out, err)
   822  	}
   823  	if strings.TrimSpace(string(out)) != "/test" {
   824  		c.Fatalf("expected output `/test`, got %q", out)
   825  	}
   826  }
   827  
   828  func (s *DockerSuite) TestContainerApiCreateEmptyConfig(c *check.C) {
   829  	config := map[string]interface{}{}
   830  
   831  	status, b, err := sockRequest("POST", "/containers/create", config)
   832  	c.Assert(err, check.IsNil)
   833  	c.Assert(status, check.Equals, http.StatusInternalServerError)
   834  
   835  	expected := "Config cannot be empty in order to create a container\n"
   836  	if body := string(b); body != expected {
   837  		c.Fatalf("Expected to get %q, got %q", expected, body)
   838  	}
   839  }
   840  
   841  func (s *DockerSuite) TestContainerApiCreateWithHostName(c *check.C) {
   842  	hostName := "test-host"
   843  	config := map[string]interface{}{
   844  		"Image":    "busybox",
   845  		"Hostname": hostName,
   846  	}
   847  
   848  	status, body, err := sockRequest("POST", "/containers/create", config)
   849  	c.Assert(err, check.IsNil)
   850  	c.Assert(status, check.Equals, http.StatusCreated)
   851  
   852  	var container types.ContainerCreateResponse
   853  	if err := json.Unmarshal(body, &container); err != nil {
   854  		c.Fatal(err)
   855  	}
   856  
   857  	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
   858  	c.Assert(err, check.IsNil)
   859  	c.Assert(status, check.Equals, http.StatusOK)
   860  
   861  	var containerJSON types.ContainerJSON
   862  	if err := json.Unmarshal(body, &containerJSON); err != nil {
   863  		c.Fatal(err)
   864  	}
   865  
   866  	if containerJSON.Config.Hostname != hostName {
   867  		c.Fatalf("Mismatched Hostname, Expected %s, Actual: %s ", hostName, containerJSON.Config.Hostname)
   868  	}
   869  }
   870  
   871  func (s *DockerSuite) TestContainerApiCreateWithDomainName(c *check.C) {
   872  	domainName := "test-domain"
   873  	config := map[string]interface{}{
   874  		"Image":      "busybox",
   875  		"Domainname": domainName,
   876  	}
   877  
   878  	status, body, err := sockRequest("POST", "/containers/create", config)
   879  	c.Assert(err, check.IsNil)
   880  	c.Assert(status, check.Equals, http.StatusCreated)
   881  
   882  	var container types.ContainerCreateResponse
   883  	if err := json.Unmarshal(body, &container); err != nil {
   884  		c.Fatal(err)
   885  	}
   886  
   887  	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
   888  	c.Assert(err, check.IsNil)
   889  	c.Assert(status, check.Equals, http.StatusOK)
   890  
   891  	var containerJSON types.ContainerJSON
   892  	if err := json.Unmarshal(body, &containerJSON); err != nil {
   893  		c.Fatal(err)
   894  	}
   895  
   896  	if containerJSON.Config.Domainname != domainName {
   897  		c.Fatalf("Mismatched Domainname, Expected %s, Actual: %s ", domainName, containerJSON.Config.Domainname)
   898  	}
   899  }
   900  
   901  func (s *DockerSuite) TestContainerApiCreateNetworkMode(c *check.C) {
   902  	UtilCreateNetworkMode(c, "host")
   903  	UtilCreateNetworkMode(c, "bridge")
   904  	UtilCreateNetworkMode(c, "container:web1")
   905  }
   906  
   907  func UtilCreateNetworkMode(c *check.C, networkMode string) {
   908  	config := map[string]interface{}{
   909  		"Image":      "busybox",
   910  		"HostConfig": map[string]interface{}{"NetworkMode": networkMode},
   911  	}
   912  
   913  	status, body, err := sockRequest("POST", "/containers/create", config)
   914  	c.Assert(err, check.IsNil)
   915  	c.Assert(status, check.Equals, http.StatusCreated)
   916  
   917  	var container types.ContainerCreateResponse
   918  	if err := json.Unmarshal(body, &container); err != nil {
   919  		c.Fatal(err)
   920  	}
   921  
   922  	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
   923  	c.Assert(err, check.IsNil)
   924  	c.Assert(status, check.Equals, http.StatusOK)
   925  
   926  	var containerJSON types.ContainerJSON
   927  	if err := json.Unmarshal(body, &containerJSON); err != nil {
   928  		c.Fatal(err)
   929  	}
   930  
   931  	if containerJSON.HostConfig.NetworkMode != runconfig.NetworkMode(networkMode) {
   932  		c.Fatalf("Mismatched NetworkMode, Expected %s, Actual: %s ", networkMode, containerJSON.HostConfig.NetworkMode)
   933  	}
   934  }
   935  
   936  func (s *DockerSuite) TestContainerApiCreateWithCpuSharesCpuset(c *check.C) {
   937  	config := map[string]interface{}{
   938  		"Image":      "busybox",
   939  		"CpuShares":  512,
   940  		"CpusetCpus": "0,1",
   941  	}
   942  
   943  	status, body, err := sockRequest("POST", "/containers/create", config)
   944  	c.Assert(err, check.IsNil)
   945  	c.Assert(status, check.Equals, http.StatusCreated)
   946  
   947  	var container types.ContainerCreateResponse
   948  	if err := json.Unmarshal(body, &container); err != nil {
   949  		c.Fatal(err)
   950  	}
   951  
   952  	status, body, err = sockRequest("GET", "/containers/"+container.ID+"/json", nil)
   953  	c.Assert(err, check.IsNil)
   954  	c.Assert(status, check.Equals, http.StatusOK)
   955  
   956  	var containerJson types.ContainerJSON
   957  
   958  	c.Assert(json.Unmarshal(body, &containerJson), check.IsNil)
   959  
   960  	out, err := inspectField(containerJson.Id, "HostConfig.CpuShares")
   961  	c.Assert(err, check.IsNil)
   962  	c.Assert(out, check.Equals, "512")
   963  
   964  	outCpuset, errCpuset := inspectField(containerJson.Id, "HostConfig.CpusetCpus")
   965  	c.Assert(errCpuset, check.IsNil, check.Commentf("Output: %s", outCpuset))
   966  	c.Assert(outCpuset, check.Equals, "0,1")
   967  }
   968  
   969  func (s *DockerSuite) TestContainerApiVerifyHeader(c *check.C) {
   970  	config := map[string]interface{}{
   971  		"Image": "busybox",
   972  	}
   973  
   974  	create := func(ct string) (*http.Response, io.ReadCloser, error) {
   975  		jsonData := bytes.NewBuffer(nil)
   976  		if err := json.NewEncoder(jsonData).Encode(config); err != nil {
   977  			c.Fatal(err)
   978  		}
   979  		return sockRequestRaw("POST", "/containers/create", jsonData, ct)
   980  	}
   981  
   982  	// Try with no content-type
   983  	res, body, err := create("")
   984  	c.Assert(err, check.IsNil)
   985  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
   986  	body.Close()
   987  
   988  	// Try with wrong content-type
   989  	res, body, err = create("application/xml")
   990  	c.Assert(err, check.IsNil)
   991  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
   992  	body.Close()
   993  
   994  	// now application/json
   995  	res, body, err = create("application/json")
   996  	c.Assert(err, check.IsNil)
   997  	c.Assert(res.StatusCode, check.Equals, http.StatusCreated)
   998  	body.Close()
   999  }
  1000  
  1001  //Issue 14230. daemon should return 500 for invalid port syntax
  1002  func (s *DockerSuite) TestContainerApiInvalidPortSyntax(c *check.C) {
  1003  	config := `{
  1004  				  "Image": "busybox",
  1005  				  "HostConfig": {
  1006  					"PortBindings": {
  1007  					  "19039;1230": [
  1008  						{}
  1009  					  ]
  1010  					}
  1011  				  }
  1012  				}`
  1013  
  1014  	res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
  1015  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
  1016  	c.Assert(err, check.IsNil)
  1017  
  1018  	b, err := readBody(body)
  1019  	if err != nil {
  1020  		c.Fatal(err)
  1021  	}
  1022  	c.Assert(strings.Contains(string(b[:]), "Invalid port"), check.Equals, true)
  1023  }
  1024  
  1025  // Issue 7941 - test to make sure a "null" in JSON is just ignored.
  1026  // W/o this fix a null in JSON would be parsed into a string var as "null"
  1027  func (s *DockerSuite) TestContainerApiPostCreateNull(c *check.C) {
  1028  	config := `{
  1029  		"Hostname":"",
  1030  		"Domainname":"",
  1031  		"Memory":0,
  1032  		"MemorySwap":0,
  1033  		"CpuShares":0,
  1034  		"Cpuset":null,
  1035  		"AttachStdin":true,
  1036  		"AttachStdout":true,
  1037  		"AttachStderr":true,
  1038  		"PortSpecs":null,
  1039  		"ExposedPorts":{},
  1040  		"Tty":true,
  1041  		"OpenStdin":true,
  1042  		"StdinOnce":true,
  1043  		"Env":[],
  1044  		"Cmd":"ls",
  1045  		"Image":"busybox",
  1046  		"Volumes":{},
  1047  		"WorkingDir":"",
  1048  		"Entrypoint":null,
  1049  		"NetworkDisabled":false,
  1050  		"OnBuild":null}`
  1051  
  1052  	res, body, err := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
  1053  	c.Assert(res.StatusCode, check.Equals, http.StatusCreated)
  1054  	c.Assert(err, check.IsNil)
  1055  
  1056  	b, err := readBody(body)
  1057  	if err != nil {
  1058  		c.Fatal(err)
  1059  	}
  1060  	type createResp struct {
  1061  		Id string
  1062  	}
  1063  	var container createResp
  1064  	if err := json.Unmarshal(b, &container); err != nil {
  1065  		c.Fatal(err)
  1066  	}
  1067  
  1068  	out, err := inspectField(container.Id, "HostConfig.CpusetCpus")
  1069  	if err != nil {
  1070  		c.Fatal(err, out)
  1071  	}
  1072  	if out != "" {
  1073  		c.Fatalf("expected empty string, got %q", out)
  1074  	}
  1075  
  1076  	outMemory, errMemory := inspectField(container.Id, "HostConfig.Memory")
  1077  	c.Assert(outMemory, check.Equals, "0")
  1078  	if errMemory != nil {
  1079  		c.Fatal(errMemory, outMemory)
  1080  	}
  1081  	outMemorySwap, errMemorySwap := inspectField(container.Id, "HostConfig.MemorySwap")
  1082  	c.Assert(outMemorySwap, check.Equals, "0")
  1083  	if errMemorySwap != nil {
  1084  		c.Fatal(errMemorySwap, outMemorySwap)
  1085  	}
  1086  }
  1087  
  1088  func (s *DockerSuite) TestCreateWithTooLowMemoryLimit(c *check.C) {
  1089  	config := `{
  1090  		"Image":     "busybox",
  1091  		"Cmd":       "ls",
  1092  		"OpenStdin": true,
  1093  		"CpuShares": 100,
  1094  		"Memory":    524287
  1095  	}`
  1096  
  1097  	res, body, _ := sockRequestRaw("POST", "/containers/create", strings.NewReader(config), "application/json")
  1098  	b, err2 := readBody(body)
  1099  	if err2 != nil {
  1100  		c.Fatal(err2)
  1101  	}
  1102  
  1103  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
  1104  	c.Assert(strings.Contains(string(b), "Minimum memory limit allowed is 4MB"), check.Equals, true)
  1105  }
  1106  
  1107  func (s *DockerSuite) TestStartWithTooLowMemoryLimit(c *check.C) {
  1108  	out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "create", "busybox"))
  1109  	if err != nil {
  1110  		c.Fatal(err, out)
  1111  	}
  1112  
  1113  	containerID := strings.TrimSpace(out)
  1114  
  1115  	config := `{
  1116                  "CpuShares": 100,
  1117                  "Memory":    524287
  1118          }`
  1119  
  1120  	res, body, _ := sockRequestRaw("POST", "/containers/"+containerID+"/start", strings.NewReader(config), "application/json")
  1121  	b, err2 := readBody(body)
  1122  	if err2 != nil {
  1123  		c.Fatal(err2)
  1124  	}
  1125  
  1126  	c.Assert(res.StatusCode, check.Equals, http.StatusInternalServerError)
  1127  	c.Assert(strings.Contains(string(b), "Minimum memory limit allowed is 4MB"), check.Equals, true)
  1128  }
  1129  
  1130  func (s *DockerSuite) TestContainerApiRename(c *check.C) {
  1131  	runCmd := exec.Command(dockerBinary, "run", "--name", "TestContainerApiRename", "-d", "busybox", "sh")
  1132  	out, _, err := runCommandWithOutput(runCmd)
  1133  	c.Assert(err, check.IsNil)
  1134  
  1135  	containerID := strings.TrimSpace(out)
  1136  	newName := "TestContainerApiRenameNew"
  1137  	statusCode, _, err := sockRequest("POST", "/containers/"+containerID+"/rename?name="+newName, nil)
  1138  
  1139  	// 204 No Content is expected, not 200
  1140  	c.Assert(statusCode, check.Equals, http.StatusNoContent)
  1141  	c.Assert(err, check.IsNil)
  1142  
  1143  	name, err := inspectField(containerID, "Name")
  1144  	if name != "/"+newName {
  1145  		c.Fatalf("Failed to rename container, expected %v, got %v. Container rename API failed", newName, name)
  1146  	}
  1147  }
  1148  
  1149  func (s *DockerSuite) TestContainerApiKill(c *check.C) {
  1150  	name := "test-api-kill"
  1151  	runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
  1152  	out, _, err := runCommandWithOutput(runCmd)
  1153  	if err != nil {
  1154  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
  1155  	}
  1156  
  1157  	status, _, err := sockRequest("POST", "/containers/"+name+"/kill", nil)
  1158  	c.Assert(status, check.Equals, http.StatusNoContent)
  1159  	c.Assert(err, check.IsNil)
  1160  
  1161  	state, err := inspectField(name, "State.Running")
  1162  	if err != nil {
  1163  		c.Fatal(err)
  1164  	}
  1165  	if state != "false" {
  1166  		c.Fatalf("got wrong State from container %s: %q", name, state)
  1167  	}
  1168  }
  1169  
  1170  func (s *DockerSuite) TestContainerApiRestart(c *check.C) {
  1171  	name := "test-api-restart"
  1172  	runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
  1173  	out, _, err := runCommandWithOutput(runCmd)
  1174  	if err != nil {
  1175  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
  1176  	}
  1177  
  1178  	status, _, err := sockRequest("POST", "/containers/"+name+"/restart?t=1", nil)
  1179  	c.Assert(status, check.Equals, http.StatusNoContent)
  1180  	c.Assert(err, check.IsNil)
  1181  
  1182  	if err := waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 5); err != nil {
  1183  		c.Fatal(err)
  1184  	}
  1185  }
  1186  
  1187  func (s *DockerSuite) TestContainerApiRestartNotimeoutParam(c *check.C) {
  1188  	name := "test-api-restart-no-timeout-param"
  1189  	runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
  1190  	out, _, err := runCommandWithOutput(runCmd)
  1191  	if err != nil {
  1192  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
  1193  	}
  1194  	id := strings.TrimSpace(out)
  1195  	c.Assert(waitRun(id), check.IsNil)
  1196  
  1197  	status, _, err := sockRequest("POST", "/containers/"+name+"/restart", nil)
  1198  	c.Assert(status, check.Equals, http.StatusNoContent)
  1199  	c.Assert(err, check.IsNil)
  1200  
  1201  	if err := waitInspect(name, "{{ .State.Restarting  }} {{ .State.Running  }}", "false true", 5); err != nil {
  1202  		c.Fatal(err)
  1203  	}
  1204  }
  1205  
  1206  func (s *DockerSuite) TestContainerApiStart(c *check.C) {
  1207  	name := "testing-start"
  1208  	config := map[string]interface{}{
  1209  		"Image":     "busybox",
  1210  		"Cmd":       []string{"/bin/sh", "-c", "/bin/top"},
  1211  		"OpenStdin": true,
  1212  	}
  1213  
  1214  	status, _, err := sockRequest("POST", "/containers/create?name="+name, config)
  1215  	c.Assert(status, check.Equals, http.StatusCreated)
  1216  	c.Assert(err, check.IsNil)
  1217  
  1218  	conf := make(map[string]interface{})
  1219  	status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
  1220  	c.Assert(status, check.Equals, http.StatusNoContent)
  1221  	c.Assert(err, check.IsNil)
  1222  
  1223  	// second call to start should give 304
  1224  	status, _, err = sockRequest("POST", "/containers/"+name+"/start", conf)
  1225  	c.Assert(status, check.Equals, http.StatusNotModified)
  1226  	c.Assert(err, check.IsNil)
  1227  }
  1228  
  1229  func (s *DockerSuite) TestContainerApiStop(c *check.C) {
  1230  	name := "test-api-stop"
  1231  	runCmd := exec.Command(dockerBinary, "run", "-di", "--name", name, "busybox", "top")
  1232  	out, _, err := runCommandWithOutput(runCmd)
  1233  	if err != nil {
  1234  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
  1235  	}
  1236  
  1237  	status, _, err := sockRequest("POST", "/containers/"+name+"/stop?t=1", nil)
  1238  	c.Assert(status, check.Equals, http.StatusNoContent)
  1239  	c.Assert(err, check.IsNil)
  1240  
  1241  	if err := waitInspect(name, "{{ .State.Running  }}", "false", 5); err != nil {
  1242  		c.Fatal(err)
  1243  	}
  1244  
  1245  	// second call to start should give 304
  1246  	status, _, err = sockRequest("POST", "/containers/"+name+"/stop?t=1", nil)
  1247  	c.Assert(status, check.Equals, http.StatusNotModified)
  1248  	c.Assert(err, check.IsNil)
  1249  }
  1250  
  1251  func (s *DockerSuite) TestContainerApiWait(c *check.C) {
  1252  	name := "test-api-wait"
  1253  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "sleep", "5")
  1254  	out, _, err := runCommandWithOutput(runCmd)
  1255  	if err != nil {
  1256  		c.Fatalf("Error on container creation: %v, output: %q", err, out)
  1257  	}
  1258  
  1259  	status, body, err := sockRequest("POST", "/containers/"+name+"/wait", nil)
  1260  	c.Assert(status, check.Equals, http.StatusOK)
  1261  	c.Assert(err, check.IsNil)
  1262  
  1263  	if err := waitInspect(name, "{{ .State.Running  }}", "false", 5); err != nil {
  1264  		c.Fatal(err)
  1265  	}
  1266  
  1267  	var waitres types.ContainerWaitResponse
  1268  	if err := json.Unmarshal(body, &waitres); err != nil {
  1269  		c.Fatalf("unable to unmarshal response body: %v", err)
  1270  	}
  1271  
  1272  	if waitres.StatusCode != 0 {
  1273  		c.Fatalf("Expected wait response StatusCode to be 0, got %d", waitres.StatusCode)
  1274  	}
  1275  }
  1276  
  1277  func (s *DockerSuite) TestContainerApiCopy(c *check.C) {
  1278  	name := "test-container-api-copy"
  1279  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt")
  1280  	_, err := runCommand(runCmd)
  1281  	c.Assert(err, check.IsNil)
  1282  
  1283  	postData := types.CopyConfig{
  1284  		Resource: "/test.txt",
  1285  	}
  1286  
  1287  	status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
  1288  	c.Assert(err, check.IsNil)
  1289  	c.Assert(status, check.Equals, http.StatusOK)
  1290  
  1291  	found := false
  1292  	for tarReader := tar.NewReader(bytes.NewReader(body)); ; {
  1293  		h, err := tarReader.Next()
  1294  		if err != nil {
  1295  			if err == io.EOF {
  1296  				break
  1297  			}
  1298  			c.Fatal(err)
  1299  		}
  1300  		if h.Name == "test.txt" {
  1301  			found = true
  1302  			break
  1303  		}
  1304  	}
  1305  	c.Assert(found, check.Equals, true)
  1306  }
  1307  
  1308  func (s *DockerSuite) TestContainerApiCopyResourcePathEmpty(c *check.C) {
  1309  	name := "test-container-api-copy-resource-empty"
  1310  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox", "touch", "/test.txt")
  1311  	_, err := runCommand(runCmd)
  1312  	c.Assert(err, check.IsNil)
  1313  
  1314  	postData := types.CopyConfig{
  1315  		Resource: "",
  1316  	}
  1317  
  1318  	status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
  1319  	c.Assert(err, check.IsNil)
  1320  	c.Assert(status, check.Equals, http.StatusInternalServerError)
  1321  	c.Assert(string(body), check.Matches, "Path cannot be empty\n")
  1322  }
  1323  
  1324  func (s *DockerSuite) TestContainerApiCopyResourcePathNotFound(c *check.C) {
  1325  	name := "test-container-api-copy-resource-not-found"
  1326  	runCmd := exec.Command(dockerBinary, "run", "--name", name, "busybox")
  1327  	_, err := runCommand(runCmd)
  1328  	c.Assert(err, check.IsNil)
  1329  
  1330  	postData := types.CopyConfig{
  1331  		Resource: "/notexist",
  1332  	}
  1333  
  1334  	status, body, err := sockRequest("POST", "/containers/"+name+"/copy", postData)
  1335  	c.Assert(err, check.IsNil)
  1336  	c.Assert(status, check.Equals, http.StatusInternalServerError)
  1337  	c.Assert(string(body), check.Matches, "Could not find the file /notexist in container "+name+"\n")
  1338  }
  1339  
  1340  func (s *DockerSuite) TestContainerApiCopyContainerNotFound(c *check.C) {
  1341  	postData := types.CopyConfig{
  1342  		Resource: "/something",
  1343  	}
  1344  
  1345  	status, _, err := sockRequest("POST", "/containers/notexists/copy", postData)
  1346  	c.Assert(err, check.IsNil)
  1347  	c.Assert(status, check.Equals, http.StatusNotFound)
  1348  }
  1349  
  1350  func (s *DockerSuite) TestContainerApiDelete(c *check.C) {
  1351  	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
  1352  	out, _, err := runCommandWithOutput(runCmd)
  1353  	c.Assert(err, check.IsNil)
  1354  
  1355  	id := strings.TrimSpace(out)
  1356  	c.Assert(waitRun(id), check.IsNil)
  1357  
  1358  	stopCmd := exec.Command(dockerBinary, "stop", id)
  1359  	_, err = runCommand(stopCmd)
  1360  	c.Assert(err, check.IsNil)
  1361  
  1362  	status, _, err := sockRequest("DELETE", "/containers/"+id, nil)
  1363  	c.Assert(err, check.IsNil)
  1364  	c.Assert(status, check.Equals, http.StatusNoContent)
  1365  }
  1366  
  1367  func (s *DockerSuite) TestContainerApiDeleteNotExist(c *check.C) {
  1368  	status, body, err := sockRequest("DELETE", "/containers/doesnotexist", nil)
  1369  	c.Assert(err, check.IsNil)
  1370  	c.Assert(status, check.Equals, http.StatusNotFound)
  1371  	c.Assert(string(body), check.Matches, "no such id: doesnotexist\n")
  1372  }
  1373  
  1374  func (s *DockerSuite) TestContainerApiDeleteForce(c *check.C) {
  1375  	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
  1376  	out, _, err := runCommandWithOutput(runCmd)
  1377  	c.Assert(err, check.IsNil)
  1378  
  1379  	id := strings.TrimSpace(out)
  1380  	c.Assert(waitRun(id), check.IsNil)
  1381  
  1382  	status, _, err := sockRequest("DELETE", "/containers/"+id+"?force=1", nil)
  1383  	c.Assert(err, check.IsNil)
  1384  	c.Assert(status, check.Equals, http.StatusNoContent)
  1385  }
  1386  
  1387  func (s *DockerSuite) TestContainerApiDeleteRemoveLinks(c *check.C) {
  1388  	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "tlink1", "busybox", "top")
  1389  	out, _, err := runCommandWithOutput(runCmd)
  1390  	c.Assert(err, check.IsNil)
  1391  
  1392  	id := strings.TrimSpace(out)
  1393  	c.Assert(waitRun(id), check.IsNil)
  1394  
  1395  	runCmd = exec.Command(dockerBinary, "run", "--link", "tlink1:tlink1", "--name", "tlink2", "-d", "busybox", "top")
  1396  	out, _, err = runCommandWithOutput(runCmd)
  1397  	c.Assert(err, check.IsNil)
  1398  
  1399  	id2 := strings.TrimSpace(out)
  1400  	c.Assert(waitRun(id2), check.IsNil)
  1401  
  1402  	links, err := inspectFieldJSON(id2, "HostConfig.Links")
  1403  	c.Assert(err, check.IsNil)
  1404  
  1405  	if links != "[\"/tlink1:/tlink2/tlink1\"]" {
  1406  		c.Fatal("expected to have links between containers")
  1407  	}
  1408  
  1409  	status, _, err := sockRequest("DELETE", "/containers/tlink2/tlink1?link=1", nil)
  1410  	c.Assert(err, check.IsNil)
  1411  	c.Assert(status, check.Equals, http.StatusNoContent)
  1412  
  1413  	linksPostRm, err := inspectFieldJSON(id2, "HostConfig.Links")
  1414  	c.Assert(err, check.IsNil)
  1415  
  1416  	if linksPostRm != "null" {
  1417  		c.Fatal("call to api deleteContainer links should have removed the specified links")
  1418  	}
  1419  }
  1420  
  1421  func (s *DockerSuite) TestContainerApiDeleteConflict(c *check.C) {
  1422  	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
  1423  	out, _, err := runCommandWithOutput(runCmd)
  1424  	c.Assert(err, check.IsNil)
  1425  
  1426  	id := strings.TrimSpace(out)
  1427  	c.Assert(waitRun(id), check.IsNil)
  1428  
  1429  	status, _, err := sockRequest("DELETE", "/containers/"+id, nil)
  1430  	c.Assert(status, check.Equals, http.StatusConflict)
  1431  	c.Assert(err, check.IsNil)
  1432  }
  1433  
  1434  func (s *DockerSuite) TestContainerApiDeleteRemoveVolume(c *check.C) {
  1435  	testRequires(c, SameHostDaemon)
  1436  
  1437  	runCmd := exec.Command(dockerBinary, "run", "-d", "-v", "/testvolume", "busybox", "top")
  1438  	out, _, err := runCommandWithOutput(runCmd)
  1439  	c.Assert(err, check.IsNil)
  1440  
  1441  	id := strings.TrimSpace(out)
  1442  	c.Assert(waitRun(id), check.IsNil)
  1443  
  1444  	vol, err := inspectFieldMap(id, "Volumes", "/testvolume")
  1445  	c.Assert(err, check.IsNil)
  1446  
  1447  	_, err = os.Stat(vol)
  1448  	c.Assert(err, check.IsNil)
  1449  
  1450  	status, _, err := sockRequest("DELETE", "/containers/"+id+"?v=1&force=1", nil)
  1451  	c.Assert(status, check.Equals, http.StatusNoContent)
  1452  	c.Assert(err, check.IsNil)
  1453  
  1454  	if _, err := os.Stat(vol); !os.IsNotExist(err) {
  1455  		c.Fatalf("expected to get ErrNotExist error, got %v", err)
  1456  	}
  1457  }
  1458  
  1459  // Regression test for https://github.com/docker/docker/issues/6231
  1460  func (s *DockerSuite) TestContainersApiChunkedEncoding(c *check.C) {
  1461  	out, _ := dockerCmd(c, "create", "-v", "/foo", "busybox", "true")
  1462  	id := strings.TrimSpace(out)
  1463  
  1464  	conn, err := sockConn(time.Duration(10 * time.Second))
  1465  	if err != nil {
  1466  		c.Fatal(err)
  1467  	}
  1468  	client := httputil.NewClientConn(conn, nil)
  1469  	defer client.Close()
  1470  
  1471  	bindCfg := strings.NewReader(`{"Binds": ["/tmp:/foo"]}`)
  1472  	req, err := http.NewRequest("POST", "/containers/"+id+"/start", bindCfg)
  1473  	if err != nil {
  1474  		c.Fatal(err)
  1475  	}
  1476  	req.Header.Set("Content-Type", "application/json")
  1477  	// This is a cheat to make the http request do chunked encoding
  1478  	// Otherwise (just setting the Content-Encoding to chunked) net/http will overwrite
  1479  	// https://golang.org/src/pkg/net/http/request.go?s=11980:12172
  1480  	req.ContentLength = -1
  1481  
  1482  	resp, err := client.Do(req)
  1483  	if err != nil {
  1484  		c.Fatalf("error starting container with chunked encoding: %v", err)
  1485  	}
  1486  	resp.Body.Close()
  1487  	if resp.StatusCode != 204 {
  1488  		c.Fatalf("expected status code 204, got %d", resp.StatusCode)
  1489  	}
  1490  
  1491  	out, err = inspectFieldJSON(id, "HostConfig.Binds")
  1492  	if err != nil {
  1493  		c.Fatal(err)
  1494  	}
  1495  
  1496  	var binds []string
  1497  	if err := json.NewDecoder(strings.NewReader(out)).Decode(&binds); err != nil {
  1498  		c.Fatal(err)
  1499  	}
  1500  	if len(binds) != 1 {
  1501  		c.Fatalf("got unexpected binds: %v", binds)
  1502  	}
  1503  
  1504  	expected := "/tmp:/foo"
  1505  	if binds[0] != expected {
  1506  		c.Fatalf("got incorrect bind spec, wanted %s, got: %s", expected, binds[0])
  1507  	}
  1508  }
  1509  
  1510  func (s *DockerSuite) TestPostContainerStop(c *check.C) {
  1511  	runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top")
  1512  	out, _, err := runCommandWithOutput(runCmd)
  1513  	c.Assert(err, check.IsNil)
  1514  
  1515  	containerID := strings.TrimSpace(out)
  1516  	c.Assert(waitRun(containerID), check.IsNil)
  1517  
  1518  	statusCode, _, err := sockRequest("POST", "/containers/"+containerID+"/stop", nil)
  1519  
  1520  	// 204 No Content is expected, not 200
  1521  	c.Assert(statusCode, check.Equals, http.StatusNoContent)
  1522  	c.Assert(err, check.IsNil)
  1523  
  1524  	if err := waitInspect(containerID, "{{ .State.Running  }}", "false", 5); err != nil {
  1525  		c.Fatal(err)
  1526  	}
  1527  }
  1528  
  1529  // #14170
  1530  func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceEntrypoint(c *check.C) {
  1531  	config := struct {
  1532  		Image      string
  1533  		Entrypoint string
  1534  		Cmd        []string
  1535  	}{"busybox", "echo", []string{"hello", "world"}}
  1536  	_, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
  1537  	c.Assert(err, check.IsNil)
  1538  	out, _ := dockerCmd(c, "start", "-a", "echotest")
  1539  	c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
  1540  
  1541  	config2 := struct {
  1542  		Image      string
  1543  		Entrypoint []string
  1544  		Cmd        []string
  1545  	}{"busybox", []string{"echo"}, []string{"hello", "world"}}
  1546  	_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
  1547  	c.Assert(err, check.IsNil)
  1548  	out, _ = dockerCmd(c, "start", "-a", "echotest2")
  1549  	c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
  1550  }
  1551  
  1552  // #14170
  1553  func (s *DockerSuite) TestPostContainersCreateWithStringOrSliceCmd(c *check.C) {
  1554  	config := struct {
  1555  		Image      string
  1556  		Entrypoint string
  1557  		Cmd        string
  1558  	}{"busybox", "echo", "hello world"}
  1559  	_, _, err := sockRequest("POST", "/containers/create?name=echotest", config)
  1560  	c.Assert(err, check.IsNil)
  1561  	out, _ := dockerCmd(c, "start", "-a", "echotest")
  1562  	c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
  1563  
  1564  	config2 := struct {
  1565  		Image string
  1566  		Cmd   []string
  1567  	}{"busybox", []string{"echo", "hello", "world"}}
  1568  	_, _, err = sockRequest("POST", "/containers/create?name=echotest2", config2)
  1569  	c.Assert(err, check.IsNil)
  1570  	out, _ = dockerCmd(c, "start", "-a", "echotest2")
  1571  	c.Assert(strings.TrimSpace(out), check.Equals, "hello world")
  1572  }