github.com/ruphin/docker@v1.10.1/integration-cli/docker_api_exec_test.go (about)

     1  // +build !test_no_exec
     2  
     3  package main
     4  
     5  import (
     6  	"bytes"
     7  	"encoding/json"
     8  	"fmt"
     9  	"net/http"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/docker/docker/pkg/integration/checker"
    14  	"github.com/go-check/check"
    15  )
    16  
    17  // Regression test for #9414
    18  func (s *DockerSuite) TestExecApiCreateNoCmd(c *check.C) {
    19  	testRequires(c, DaemonIsLinux)
    20  	name := "exec_test"
    21  	dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
    22  
    23  	status, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": nil})
    24  	c.Assert(err, checker.IsNil)
    25  	c.Assert(status, checker.Equals, http.StatusInternalServerError)
    26  
    27  	comment := check.Commentf("Expected message when creating exec command with no Cmd specified")
    28  	c.Assert(string(body), checker.Contains, "No exec command specified", comment)
    29  }
    30  
    31  func (s *DockerSuite) TestExecApiCreateNoValidContentType(c *check.C) {
    32  	testRequires(c, DaemonIsLinux)
    33  	name := "exec_test"
    34  	dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
    35  
    36  	jsonData := bytes.NewBuffer(nil)
    37  	if err := json.NewEncoder(jsonData).Encode(map[string]interface{}{"Cmd": nil}); err != nil {
    38  		c.Fatalf("Can not encode data to json %s", err)
    39  	}
    40  
    41  	res, body, err := sockRequestRaw("POST", fmt.Sprintf("/containers/%s/exec", name), jsonData, "text/plain")
    42  	c.Assert(err, checker.IsNil)
    43  	c.Assert(res.StatusCode, checker.Equals, http.StatusInternalServerError)
    44  
    45  	b, err := readBody(body)
    46  	c.Assert(err, checker.IsNil)
    47  
    48  	comment := check.Commentf("Expected message when creating exec command with invalid Content-Type specified")
    49  	c.Assert(string(b), checker.Contains, "Content-Type specified", comment)
    50  }
    51  
    52  func (s *DockerSuite) TestExecApiCreateContainerPaused(c *check.C) {
    53  	testRequires(c, DaemonIsLinux)
    54  	name := "exec_create_test"
    55  	dockerCmd(c, "run", "-d", "-t", "--name", name, "busybox", "/bin/sh")
    56  
    57  	dockerCmd(c, "pause", name)
    58  	status, body, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": []string{"true"}})
    59  	c.Assert(err, checker.IsNil)
    60  	c.Assert(status, checker.Equals, http.StatusConflict)
    61  
    62  	comment := check.Commentf("Expected message when creating exec command with Container s% is paused", name)
    63  	c.Assert(string(body), checker.Contains, "Container "+name+" is paused, unpause the container before exec", comment)
    64  }
    65  
    66  func (s *DockerSuite) TestExecAPIStart(c *check.C) {
    67  	testRequires(c, DaemonIsLinux) // Uses pause/unpause but bits may be salvagable to Windows to Windows CI
    68  	dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
    69  
    70  	id := createExec(c, "test")
    71  	startExec(c, id, http.StatusOK)
    72  
    73  	id = createExec(c, "test")
    74  	dockerCmd(c, "stop", "test")
    75  
    76  	startExec(c, id, http.StatusNotFound)
    77  
    78  	dockerCmd(c, "start", "test")
    79  	startExec(c, id, http.StatusNotFound)
    80  
    81  	// make sure exec is created before pausing
    82  	id = createExec(c, "test")
    83  	dockerCmd(c, "pause", "test")
    84  	startExec(c, id, http.StatusConflict)
    85  	dockerCmd(c, "unpause", "test")
    86  	startExec(c, id, http.StatusOK)
    87  }
    88  
    89  func (s *DockerSuite) TestExecAPIStartBackwardsCompatible(c *check.C) {
    90  	dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
    91  	id := createExec(c, "test")
    92  
    93  	resp, body, err := sockRequestRaw("POST", fmt.Sprintf("/v1.20/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "text/plain")
    94  	c.Assert(err, checker.IsNil)
    95  
    96  	b, err := readBody(body)
    97  	comment := check.Commentf("response body: %s", b)
    98  	c.Assert(err, checker.IsNil, comment)
    99  	c.Assert(resp.StatusCode, checker.Equals, http.StatusOK, comment)
   100  }
   101  
   102  // #19362
   103  func (s *DockerSuite) TestExecAPIStartMultipleTimesError(c *check.C) {
   104  	dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
   105  	execID := createExec(c, "test")
   106  	startExec(c, execID, http.StatusOK)
   107  
   108  	timeout := time.After(10 * time.Second)
   109  	var execJSON struct{ Running bool }
   110  	for {
   111  		select {
   112  		case <-timeout:
   113  			c.Fatal("timeout waiting for exec to start")
   114  		default:
   115  		}
   116  
   117  		inspectExec(c, execID, &execJSON)
   118  		if !execJSON.Running {
   119  			break
   120  		}
   121  	}
   122  
   123  	startExec(c, execID, http.StatusConflict)
   124  }
   125  
   126  func createExec(c *check.C, name string) string {
   127  	_, b, err := sockRequest("POST", fmt.Sprintf("/containers/%s/exec", name), map[string]interface{}{"Cmd": []string{"true"}})
   128  	c.Assert(err, checker.IsNil, check.Commentf(string(b)))
   129  
   130  	createResp := struct {
   131  		ID string `json:"Id"`
   132  	}{}
   133  	c.Assert(json.Unmarshal(b, &createResp), checker.IsNil, check.Commentf(string(b)))
   134  	return createResp.ID
   135  }
   136  
   137  func startExec(c *check.C, id string, code int) {
   138  	resp, body, err := sockRequestRaw("POST", fmt.Sprintf("/exec/%s/start", id), strings.NewReader(`{"Detach": true}`), "application/json")
   139  	c.Assert(err, checker.IsNil)
   140  
   141  	b, err := readBody(body)
   142  	comment := check.Commentf("response body: %s", b)
   143  	c.Assert(err, checker.IsNil, comment)
   144  	c.Assert(resp.StatusCode, checker.Equals, code, comment)
   145  }
   146  
   147  func inspectExec(c *check.C, id string, out interface{}) {
   148  	resp, body, err := sockRequestRaw("GET", fmt.Sprintf("/exec/%s/json", id), nil, "")
   149  	c.Assert(err, checker.IsNil)
   150  	defer body.Close()
   151  	c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
   152  	err = json.NewDecoder(body).Decode(out)
   153  	c.Assert(err, checker.IsNil)
   154  }