github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/client/container_exec_test.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net/http" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/errdefs" 15 "gotest.tools/v3/assert" 16 is "gotest.tools/v3/assert/cmp" 17 ) 18 19 func TestContainerExecCreateError(t *testing.T) { 20 client := &Client{ 21 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 22 } 23 _, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{}) 24 assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) 25 } 26 27 // TestContainerExecCreateConnectionError verifies that connection errors occurring 28 // during API-version negotiation are not shadowed by API-version errors. 29 // 30 // Regression test for https://github.com/docker/cli/issues/4890 31 func TestContainerExecCreateConnectionError(t *testing.T) { 32 client, err := NewClientWithOpts(WithAPIVersionNegotiation(), WithHost("tcp://no-such-host.invalid")) 33 assert.NilError(t, err) 34 35 _, err = client.ContainerExecCreate(context.Background(), "", types.ExecConfig{}) 36 assert.Check(t, is.ErrorType(err, IsErrConnectionFailed)) 37 } 38 39 func TestContainerExecCreate(t *testing.T) { 40 expectedURL := "/containers/container_id/exec" 41 client := &Client{ 42 client: newMockClient(func(req *http.Request) (*http.Response, error) { 43 if !strings.HasPrefix(req.URL.Path, expectedURL) { 44 return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) 45 } 46 if req.Method != http.MethodPost { 47 return nil, fmt.Errorf("expected POST method, got %s", req.Method) 48 } 49 // FIXME validate the content is the given ExecConfig ? 50 if err := req.ParseForm(); err != nil { 51 return nil, err 52 } 53 execConfig := &types.ExecConfig{} 54 if err := json.NewDecoder(req.Body).Decode(execConfig); err != nil { 55 return nil, err 56 } 57 if execConfig.User != "user" { 58 return nil, fmt.Errorf("expected an execConfig with User == 'user', got %v", execConfig) 59 } 60 b, err := json.Marshal(types.IDResponse{ 61 ID: "exec_id", 62 }) 63 if err != nil { 64 return nil, err 65 } 66 return &http.Response{ 67 StatusCode: http.StatusOK, 68 Body: io.NopCloser(bytes.NewReader(b)), 69 }, nil 70 }), 71 } 72 73 r, err := client.ContainerExecCreate(context.Background(), "container_id", types.ExecConfig{ 74 User: "user", 75 }) 76 if err != nil { 77 t.Fatal(err) 78 } 79 if r.ID != "exec_id" { 80 t.Fatalf("expected `exec_id`, got %s", r.ID) 81 } 82 } 83 84 func TestContainerExecStartError(t *testing.T) { 85 client := &Client{ 86 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 87 } 88 err := client.ContainerExecStart(context.Background(), "nothing", types.ExecStartCheck{}) 89 assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) 90 } 91 92 func TestContainerExecStart(t *testing.T) { 93 expectedURL := "/exec/exec_id/start" 94 client := &Client{ 95 client: newMockClient(func(req *http.Request) (*http.Response, error) { 96 if !strings.HasPrefix(req.URL.Path, expectedURL) { 97 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 98 } 99 if err := req.ParseForm(); err != nil { 100 return nil, err 101 } 102 execStartCheck := &types.ExecStartCheck{} 103 if err := json.NewDecoder(req.Body).Decode(execStartCheck); err != nil { 104 return nil, err 105 } 106 if execStartCheck.Tty || !execStartCheck.Detach { 107 return nil, fmt.Errorf("expected execStartCheck{Detach:true,Tty:false}, got %v", execStartCheck) 108 } 109 110 return &http.Response{ 111 StatusCode: http.StatusOK, 112 Body: io.NopCloser(bytes.NewReader([]byte(""))), 113 }, nil 114 }), 115 } 116 117 err := client.ContainerExecStart(context.Background(), "exec_id", types.ExecStartCheck{ 118 Detach: true, 119 Tty: false, 120 }) 121 if err != nil { 122 t.Fatal(err) 123 } 124 } 125 126 func TestContainerExecInspectError(t *testing.T) { 127 client := &Client{ 128 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 129 } 130 _, err := client.ContainerExecInspect(context.Background(), "nothing") 131 assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) 132 } 133 134 func TestContainerExecInspect(t *testing.T) { 135 expectedURL := "/exec/exec_id/json" 136 client := &Client{ 137 client: newMockClient(func(req *http.Request) (*http.Response, error) { 138 if !strings.HasPrefix(req.URL.Path, expectedURL) { 139 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL) 140 } 141 b, err := json.Marshal(types.ContainerExecInspect{ 142 ExecID: "exec_id", 143 ContainerID: "container_id", 144 }) 145 if err != nil { 146 return nil, err 147 } 148 return &http.Response{ 149 StatusCode: http.StatusOK, 150 Body: io.NopCloser(bytes.NewReader(b)), 151 }, nil 152 }), 153 } 154 155 inspect, err := client.ContainerExecInspect(context.Background(), "exec_id") 156 if err != nil { 157 t.Fatal(err) 158 } 159 if inspect.ExecID != "exec_id" { 160 t.Fatalf("expected ExecID to be `exec_id`, got %s", inspect.ExecID) 161 } 162 if inspect.ContainerID != "container_id" { 163 t.Fatalf("expected ContainerID `container_id`, got %s", inspect.ContainerID) 164 } 165 }