From 63add7fa1c486c42bd2d26f6b6b1fe384c11fc68 Mon Sep 17 00:00:00 2001 From: Zou Rui <21751189@zju.edu.cn> Date: Fri, 1 Jun 2018 16:22:29 +0800 Subject: [PATCH] test: add more test for container operations Signed-off-by: Zou Rui <21751189@zju.edu.cn> --- client/container_attach.go | 24 +++++ client/container_create_test.go | 1 + client/container_exec_test.go | 110 +++++++++++++++++++++ client/{container.go => container_logs.go} | 31 ------ client/container_upgrade.go | 20 ++++ client/container_upgrade_test.go | 50 ++++++++++ client/network_connect_test.go | 60 +++++++++++ 7 files changed, 265 insertions(+), 31 deletions(-) create mode 100644 client/container_attach.go create mode 100644 client/container_exec_test.go rename client/{container.go => container_logs.go} (50%) create mode 100644 client/container_upgrade.go create mode 100644 client/container_upgrade_test.go create mode 100644 client/network_connect_test.go diff --git a/client/container_attach.go b/client/container_attach.go new file mode 100644 index 000000000..66f310c14 --- /dev/null +++ b/client/container_attach.go @@ -0,0 +1,24 @@ +package client + +import ( + "bufio" + "context" + "net" + "net/url" +) + +// ContainerAttach attachs a container. +func (client *APIClient) ContainerAttach(ctx context.Context, name string, stdin bool) (net.Conn, *bufio.Reader, error) { + q := url.Values{} + if stdin { + q.Set("stdin", "1") + } else { + q.Set("stdin", "0") + } + + header := map[string][]string{ + "Content-Type": {"text/plain"}, + } + + return client.hijack(ctx, "/containers/"+name+"/attach", q, nil, header) +} diff --git a/client/container_create_test.go b/client/container_create_test.go index 14bd60704..8a8bffbbd 100644 --- a/client/container_create_test.go +++ b/client/container_create_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/alibaba/pouch/apis/types" + "github.com/stretchr/testify/assert" ) diff --git a/client/container_exec_test.go b/client/container_exec_test.go new file mode 100644 index 000000000..51e729090 --- /dev/null +++ b/client/container_exec_test.go @@ -0,0 +1,110 @@ +package client + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/alibaba/pouch/apis/types" + + "github.com/stretchr/testify/assert" +) + +func TestContainerCreateExecError(t *testing.T) { + client := &APIClient{ + HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")), + } + _, err := client.ContainerCreateExec(context.Background(), "nothing", &types.ExecCreateConfig{}) + if err == nil || !strings.Contains(err.Error(), "Server error") { + t.Fatalf("expected a Server Error, got %v", err) + } +} + +func TestContainerCreateExec(t *testing.T) { + expectedURL := "/containers/container_id/exec" + + httpClient := newMockClient(func(req *http.Request) (*http.Response, error) { + if !strings.HasPrefix(req.URL.Path, expectedURL) { + return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) + } + if req.Header.Get("Content-Type") == "application/json" { + createExecConfig := &types.ExecCreateConfig{} + if err := json.NewDecoder(req.Body).Decode(createExecConfig); err != nil { + return nil, fmt.Errorf("failed to parse json: %v", err) + } + } + createExecResponse := types.ExecCreateResp{ + ID: "container_id", + } + b, err := json.Marshal(createExecResponse) + if err != nil { + return nil, err + } + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewReader([]byte(b))), + }, nil + }) + + client := &APIClient{ + HTTPCli: httpClient, + } + + res, err := client.ContainerCreateExec(context.Background(), "container_id", &types.ExecCreateConfig{}) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, res.ID, "container_id") +} + +func TestContainerInspectExecError(t *testing.T) { + client := &APIClient{ + HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")), + } + _, err := client.ContainerExecInspect(context.Background(), "nothing") + if err == nil || !strings.Contains(err.Error(), "Server error") { + t.Fatalf("expected a Server Error, got %v", err) + } +} + +func TestContainerInspectExec(t *testing.T) { + expectedURL := "/exec/container_id/json" + + httpClient := newMockClient(func(req *http.Request) (*http.Response, error) { + if !strings.HasPrefix(req.URL.Path, expectedURL) { + return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) + } + if req.Method != "GET" { + return nil, fmt.Errorf("expected GET method, got %s", req.Method) + } + b, err := json.Marshal(types.ContainerExecInspect{ + ID: "exec_id", + ContainerID: "container_id", + }) + if err != nil { + return nil, err + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewReader([]byte(b))), + }, nil + }) + + client := &APIClient{ + HTTPCli: httpClient, + } + + res, err := client.ContainerExecInspect(context.Background(), "container_id") + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, res.ID, "exec_id") + assert.Equal(t, res.ContainerID, "container_id") +} diff --git a/client/container.go b/client/container_logs.go similarity index 50% rename from client/container.go rename to client/container_logs.go index 332d56e3d..dce110ebb 100644 --- a/client/container.go +++ b/client/container_logs.go @@ -1,44 +1,13 @@ package client import ( - "bufio" "context" "io" - "net" "net/url" "github.com/alibaba/pouch/apis/types" ) -// ContainerAttach attach a container -func (client *APIClient) ContainerAttach(ctx context.Context, name string, stdin bool) (net.Conn, *bufio.Reader, error) { - q := url.Values{} - if stdin { - q.Set("stdin", "1") - } else { - q.Set("stdin", "0") - } - - header := map[string][]string{ - "Content-Type": {"text/plain"}, - } - - return client.hijack(ctx, "/containers/"+name+"/attach", q, nil, header) -} - -// ContainerUpgrade upgrade a container with new image and args. -func (client *APIClient) ContainerUpgrade(ctx context.Context, name string, config types.ContainerConfig, hostConfig *types.HostConfig) error { - // TODO - upgradeConfig := types.ContainerUpgradeConfig{ - ContainerConfig: config, - HostConfig: hostConfig, - } - resp, err := client.post(ctx, "/containers/"+name+"/upgrade", url.Values{}, upgradeConfig, nil) - ensureCloseReader(resp) - - return err -} - // ContainerLogs return the logs generated by a container in an io.ReadCloser. func (client *APIClient) ContainerLogs(ctx context.Context, name string, options types.ContainerLogsOptions) (io.ReadCloser, error) { query := url.Values{} diff --git a/client/container_upgrade.go b/client/container_upgrade.go new file mode 100644 index 000000000..24d97aeef --- /dev/null +++ b/client/container_upgrade.go @@ -0,0 +1,20 @@ +package client + +import ( + "context" + "net/url" + + "github.com/alibaba/pouch/apis/types" +) + +// ContainerUpgrade upgrade a container with new image and args. +func (client *APIClient) ContainerUpgrade(ctx context.Context, name string, config types.ContainerConfig, hostConfig *types.HostConfig) error { + upgradeConfig := types.ContainerUpgradeConfig{ + ContainerConfig: config, + HostConfig: hostConfig, + } + resp, err := client.post(ctx, "/containers/"+name+"/upgrade", url.Values{}, upgradeConfig, nil) + ensureCloseReader(resp) + + return err +} diff --git a/client/container_upgrade_test.go b/client/container_upgrade_test.go new file mode 100644 index 000000000..c2c64ef91 --- /dev/null +++ b/client/container_upgrade_test.go @@ -0,0 +1,50 @@ +package client + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/alibaba/pouch/apis/types" +) + +func TestContainerUpgradeError(t *testing.T) { + client := &APIClient{ + HTTPCli: newMockClient(errorMockResponse(http.StatusInternalServerError, "Server error")), + } + err := client.ContainerUpgrade(context.Background(), "nothing", types.ContainerConfig{}, &types.HostConfig{}) + if err == nil || !strings.Contains(err.Error(), "Server error") { + t.Fatalf("expected a Server Error, got %v", err) + } +} + +func TestContainerUpgrade(t *testing.T) { + expectedURL := "/containers/container_id/upgrade" + + httpClient := newMockClient(func(req *http.Request) (*http.Response, error) { + if !strings.HasPrefix(req.URL.Path, expectedURL) { + return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) + } + if req.Header.Get("Content-Type") == "application/json" { + var upgradeConfig interface{} + if err := json.NewDecoder(req.Body).Decode(&upgradeConfig); err != nil { + return nil, fmt.Errorf("failed to parse json: %v", err) + } + } + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + }, nil + }) + client := &APIClient{ + HTTPCli: httpClient, + } + if err := client.ContainerUpgrade(context.Background(), "container_id", types.ContainerConfig{}, &types.HostConfig{}); err != nil { + t.Fatal(err) + } +} diff --git a/client/network_connect_test.go b/client/network_connect_test.go new file mode 100644 index 000000000..251b566c3 --- /dev/null +++ b/client/network_connect_test.go @@ -0,0 +1,60 @@ +package client + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strings" + "testing" + + "github.com/alibaba/pouch/apis/types" +) + +func TestNetworkConnectNotFoundError(t *testing.T) { + client := &APIClient{ + HTTPCli: newMockClient(errorMockResponse(http.StatusNotFound, "Not Found")), + } + err := client.NetworkConnect(context.Background(), "no_network", &types.NetworkConnect{}) + if err == nil || !strings.Contains(err.Error(), "Not Found") { + t.Fatalf("expected a Not Found Error, got %v", err) + } +} + +func TestNetworkConnect(t *testing.T) { + expectedURL := "/networks/network_id/connect" + + httpClient := newMockClient(func(req *http.Request) (*http.Response, error) { + if !strings.HasPrefix(req.URL.Path, expectedURL) { + return nil, fmt.Errorf("expected URL '%s', got '%s'", expectedURL, req.URL) + } + if req.Method != "POST" { + return nil, fmt.Errorf("expected POST method, got %s", req.Method) + } + + connect := &types.NetworkConnect{} + if err := json.NewDecoder(req.Body).Decode(connect); err != nil { + return nil, err + } + + if connect.Container != "container_id" { + return nil, fmt.Errorf("expected 'containerID', got %s", connect.Container) + } + + return &http.Response{ + StatusCode: http.StatusOK, + Body: ioutil.NopCloser(bytes.NewReader([]byte(""))), + }, nil + }) + + client := &APIClient{ + HTTPCli: httpClient, + } + + err := client.NetworkConnect(context.Background(), "network_id", &types.NetworkConnect{Container: "container_id"}) + if err != nil { + t.Fatal(err) + } +}