diff --git a/api.go b/api.go index 90257c39bc..b3cdb59bc0 100644 --- a/api.go +++ b/api.go @@ -40,10 +40,11 @@ func httpError(w http.ResponseWriter, err error) { } func getAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) { - var out auth.AuthConfig - out.Username = srv.runtime.authConfig.Username - out.Email = srv.runtime.authConfig.Email - b, err := json.Marshal(out) + config := &auth.AuthConfig{ + Username: srv.runtime.authConfig.Username, + Email: srv.runtime.authConfig.Email, + } + b, err := json.Marshal(config) if err != nil { return nil, err } @@ -51,8 +52,8 @@ func getAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[strin } func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) { - var config auth.AuthConfig - if err := json.NewDecoder(r.Body).Decode(&config); err != nil { + config := &auth.AuthConfig{} + if err := json.NewDecoder(r.Body).Decode(config); err != nil { return nil, err } @@ -69,7 +70,7 @@ func postAuth(srv *Server, w http.ResponseWriter, r *http.Request, vars map[stri srv.runtime.authConfig = newAuthConfig } if status != "" { - b, err := json.Marshal(ApiAuth{status}) + b, err := json.Marshal(&ApiAuth{Status: status}) if err != nil { return nil, err } @@ -113,7 +114,7 @@ func getContainersExport(srv *Server, w http.ResponseWriter, r *http.Request, va return nil, nil } -func getImages(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) { +func getImagesJson(srv *Server, w http.ResponseWriter, r *http.Request, vars map[string]string) ([]byte, error) { if err := parseForm(r); err != nil { return nil, err } @@ -474,7 +475,7 @@ func postContainersWait(srv *Server, w http.ResponseWriter, r *http.Request, var if err != nil { return nil, err } - b, err := json.Marshal(ApiWait{status}) + b, err := json.Marshal(&ApiWait{StatusCode: status}) if err != nil { return nil, err } @@ -551,7 +552,7 @@ func ListenAndServe(addr string, srv *Server, logging bool) error { "/auth": getAuth, "/version": getVersion, "/info": getInfo, - "/images/json": getImages, + "/images/json": getImagesJson, "/images/viz": getImagesViz, "/images/search": getImagesSearch, "/images/{name:.*}/history": getImagesHistory, diff --git a/api_test.go b/api_test.go index ef02fa471f..632a578612 100644 --- a/api_test.go +++ b/api_test.go @@ -12,7 +12,7 @@ import ( "time" ) -func TestAuth(t *testing.T) { +func TestGetAuth(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -50,29 +50,14 @@ func TestAuth(t *testing.T) { t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) } - authConfig = &auth.AuthConfig{} - - req, err = http.NewRequest("GET", "/auth", nil) - if err != nil { - t.Fatal(err) - } - - body, err = getAuth(srv, nil, req, nil) - if err != nil { - t.Fatal(err) - } - - err = json.Unmarshal(body, authConfig) - if err != nil { - t.Fatal(err) - } - - if authConfig.Username != "utest" { - t.Errorf("Expected username to be utest, %s found", authConfig.Username) + if runtime.authConfig.Username != authConfig.Username || + runtime.authConfig.Password != authConfig.Password || + runtime.authConfig.Email != authConfig.Email { + t.Fatalf("The auth configuration hasn't been set correctly") } } -func TestVersion(t *testing.T) { +func TestGetVersion(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -97,46 +82,7 @@ func TestVersion(t *testing.T) { } } -func TestContainersExport(t *testing.T) { - //FIXME: Implement this test -} - -func TestGetImages(t *testing.T) { - runtime, err := newTestRuntime() - if err != nil { - t.Fatal(err) - } - defer nuke(runtime) - - srv := &Server{runtime: runtime} - - // FIXME: Do more tests with filter - req, err := http.NewRequest("GET", "/images?quiet=0&all=0", nil) - if err != nil { - t.Fatal(err) - } - - body, err := getImages(srv, nil, req, nil) - if err != nil { - t.Fatal(err) - } - - images := []ApiImages{} - err = json.Unmarshal(body, &images) - if err != nil { - t.Fatal(err) - } - - if len(images) != 1 { - t.Errorf("Excepted 1 image, %d found", len(images)) - } - - if images[0].Repository != "docker-ut" { - t.Errorf("Excepted image docker-ut, %s found", images[0].Repository) - } -} - -func TestInfo(t *testing.T) { +func TestGetInfo(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -159,7 +105,7 @@ func TestInfo(t *testing.T) { } } -func TestHistory(t *testing.T) { +func TestGetImagesJson(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -168,23 +114,38 @@ func TestHistory(t *testing.T) { srv := &Server{runtime: runtime} - body, err := getImagesHistory(srv, nil, nil, map[string]string{"name": unitTestImageName}) + // FIXME: Do more tests with filter + req, err := http.NewRequest("GET", "/images/json?quiet=0&all=0", nil) if err != nil { t.Fatal(err) } - history := []ApiHistory{} - - err = json.Unmarshal(body, &history) + body, err := getImagesJson(srv, nil, req, nil) if err != nil { t.Fatal(err) } - if len(history) != 1 { - t.Errorf("Excepted 1 line, %d found", len(history)) + + images := []ApiImages{} + err = json.Unmarshal(body, &images) + if err != nil { + t.Fatal(err) + } + + if len(images) != 1 { + t.Errorf("Excepted 1 image, %d found", len(images)) + } + + if images[0].Repository != "docker-ut" { + t.Errorf("Excepted image docker-ut, %s found", images[0].Repository) } } -func TestImagesSearch(t *testing.T) { +func TestGetImagesViz(t *testing.T) { + //FIXME: Implement this test (or remove this endpoint) + t.Log("Test on implemented") +} + +func TestGetImagesSearch(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -214,7 +175,32 @@ func TestImagesSearch(t *testing.T) { } } -func TestGetImage(t *testing.T) { +func TestGetImagesHistory(t *testing.T) { + runtime, err := newTestRuntime() + if err != nil { + t.Fatal(err) + } + defer nuke(runtime) + + srv := &Server{runtime: runtime} + + body, err := getImagesHistory(srv, nil, nil, map[string]string{"name": unitTestImageName}) + if err != nil { + t.Fatal(err) + } + + history := []ApiHistory{} + + err = json.Unmarshal(body, &history) + if err != nil { + t.Fatal(err) + } + if len(history) != 1 { + t.Errorf("Excepted 1 line, %d found", len(history)) + } +} + +func TestGetImagesByName(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -239,6 +225,136 @@ func TestGetImage(t *testing.T) { } } +func TestGetContainersPs(t *testing.T) { + runtime, err := newTestRuntime() + if err != nil { + t.Fatal(err) + } + defer nuke(runtime) + + srv := &Server{runtime: runtime} + + container, err := NewBuilder(runtime).Create(&Config{ + Image: GetTestImage(runtime).Id, + Cmd: []string{"echo", "test"}, + }) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container) + + req, err := http.NewRequest("GET", "/containers?quiet=1&all=1", nil) + if err != nil { + t.Fatal(err) + } + + body, err := getContainersPs(srv, nil, req, nil) + if err != nil { + t.Fatal(err) + } + containers := []ApiContainers{} + err = json.Unmarshal(body, &containers) + if err != nil { + t.Fatal(err) + } + if len(containers) != 1 { + t.Fatalf("Excepted %d container, %d found", 1, len(containers)) + } + if containers[0].Id != container.ShortId() { + t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ShortId(), containers[0].Id) + } +} + +func TestGetContainersExport(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + +func TestGetContainerChanges(t *testing.T) { + // FIXME: Implement this test + t.Log("Test on implemented") + // r := httptest.NewRecorder() + + // req, err := http.NewRequest("GET", "/containers/"+id+"/changes", nil) + // if err != nil { + // t.Fatal(err) + // } + + // body, err := getContainersChanges(srv, r, req, nil) + // if err != nil { + // t.Fatal(err) + // } + + // if body == nil { + // t.Fatalf("Body expected, received: nil\n") + // } + + // if r.Code != http.StatusOK { + // t.Fatalf("%d OK expected, received %d\n", http.StatusNoContent, r.Code) + // } +} + +func TestPostAuth(t *testing.T) { + runtime, err := newTestRuntime() + if err != nil { + t.Fatal(err) + } + defer nuke(runtime) + + srv := &Server{runtime: runtime} + + authConfigOrig := &auth.AuthConfig{ + Username: "utest", + Email: "utest@yopmail.com", + } + runtime.authConfig = authConfigOrig + + body, err := getAuth(srv, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + + authConfig := &auth.AuthConfig{} + err = json.Unmarshal(body, authConfig) + if err != nil { + t.Fatal(err) + } + + if authConfig.Username != authConfigOrig.Username || authConfig.Email != authConfigOrig.Email { + t.Errorf("The retrieve auth mismatch with the one set.") + } +} + +func TestPostCommit(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + +func TestPostBuild(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + +func TestPostImagesCreate(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + +func TestPostImagesInsert(t *testing.T) { + //FIXME: Implement this test (or remove this endpoint) + t.Log("Test on implemented") +} + +func TestPostImagesPush(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + +func TestPostImagesTag(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") +} + func TestPostContainersCreate(t *testing.T) { runtime, err := newTestRuntime() if err != nil { @@ -295,7 +411,7 @@ func TestPostContainersCreate(t *testing.T) { } } -func TestGetContainersPs(t *testing.T) { +func TestPostContainersKill(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -304,34 +420,104 @@ func TestGetContainersPs(t *testing.T) { srv := &Server{runtime: runtime} - container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, - Cmd: []string{"echo", "test"}, - }) + container, err := NewBuilder(runtime).Create( + &Config{ + Image: GetTestImage(runtime).Id, + Cmd: []string{"/bin/cat"}, + OpenStdin: true, + }, + ) if err != nil { t.Fatal(err) } defer runtime.Destroy(container) - req, err := http.NewRequest("GET", "/containers?quiet=1&all=1", nil) - if err != nil { + if err := container.Start(); err != nil { t.Fatal(err) } - body, err := getContainersPs(srv, nil, req, nil) + // Give some time to the process to start + container.WaitTimeout(500 * time.Millisecond) + + if !container.State.Running { + t.Errorf("Container should be running") + } + + r := httptest.NewRecorder() + + body, err := postContainersKill(srv, r, nil, map[string]string{"name": container.Id}) if err != nil { t.Fatal(err) } - containers := []ApiContainers{} - err = json.Unmarshal(body, &containers) + if body != nil { + t.Fatalf("No body expected, received: %s\n", body) + } + if r.Code != http.StatusNoContent { + t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) + } + if container.State.Running { + t.Fatalf("The container hasn't been killed") + } +} + +func TestPostContainersRestart(t *testing.T) { + runtime, err := newTestRuntime() if err != nil { t.Fatal(err) } - if len(containers) != 1 { - t.Fatalf("Excepted %d container, %d found", 1, len(containers)) + defer nuke(runtime) + + srv := &Server{runtime: runtime} + + container, err := NewBuilder(runtime).Create( + &Config{ + Image: GetTestImage(runtime).Id, + Cmd: []string{"/bin/cat"}, + OpenStdin: true, + }, + ) + if err != nil { + t.Fatal(err) } - if containers[0].Id != container.ShortId() { - t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ShortId(), containers[0].Id) + defer runtime.Destroy(container) + + if err := container.Start(); err != nil { + t.Fatal(err) + } + + // Give some time to the process to start + container.WaitTimeout(500 * time.Millisecond) + + if !container.State.Running { + t.Errorf("Container should be running") + } + + r := httptest.NewRecorder() + + req, err := http.NewRequest("POST", "/containers/"+container.Id+"/restart?t=1", bytes.NewReader([]byte{})) + if err != nil { + t.Fatal(err) + } + body, err := postContainersRestart(srv, r, req, map[string]string{"name": container.Id}) + if err != nil { + t.Fatal(err) + } + if body != nil { + t.Fatalf("No body expected, received: %s\n", body) + } + if r.Code != http.StatusNoContent { + t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) + } + + // Give some time to the process to restart + container.WaitTimeout(500 * time.Millisecond) + + if !container.State.Running { + t.Fatalf("Container should be running") + } + + if err := container.Kill(); err != nil { + t.Fatal(err) } } @@ -385,34 +571,6 @@ func TestPostContainersStart(t *testing.T) { } } -func testContainerRestart(t *testing.T, srv *Server, id string) { - - r := httptest.NewRecorder() - - req, err := http.NewRequest("POST", "/containers/"+id+"/restart?t=1", nil) - if err != nil { - t.Fatal(err) - } - - body, err := postContainersRestart(srv, r, req, nil) - if err != nil { - t.Fatal(err) - } - - if body != nil { - t.Fatalf("No body expected, received: %s\n", body) - } - - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) - } -} - -// testContainerRestart(t, srv, id) -// testContainerKill(t, srv, id) -// testContainerWait(t, srv, id) -// testDeleteContainer(t, srv, id) -// testListContainers(t, srv, 0) func TestPostContainersStop(t *testing.T) { runtime, err := newTestRuntime() if err != nil { @@ -467,52 +625,53 @@ func TestPostContainersStop(t *testing.T) { } } -func testContainerKill(t *testing.T, srv *Server, id string) { - - r := httptest.NewRecorder() - - req, err := http.NewRequest("POST", "/containers/"+id+"/kill", nil) +func TestPostContainersWait(t *testing.T) { + runtime, err := newTestRuntime() if err != nil { t.Fatal(err) } + defer nuke(runtime) - body, err := postContainersKill(srv, r, req, nil) + srv := &Server{runtime: runtime} + + container, err := NewBuilder(runtime).Create( + &Config{ + Image: GetTestImage(runtime).Id, + Cmd: []string{"/bin/sleep", "1"}, + OpenStdin: true, + }, + ) if err != nil { t.Fatal(err) } + defer runtime.Destroy(container) - if body != nil { - t.Fatalf("No body expected, received: %s\n", body) + if err := container.Start(); err != nil { + t.Fatal(err) } - if r.Code != http.StatusNoContent { - t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) + setTimeout(t, "Wait timed out", 3*time.Second, func() { + body, err := postContainersWait(srv, nil, nil, nil) + if err != nil { + t.Fatal(err) + } + apiWait := &ApiWait{} + if err := json.Unmarshal(body, apiWait); err != nil { + t.Fatal(err) + } + if apiWait.StatusCode != 0 { + t.Fatalf("Non zero exit code for sleep: %d\n", apiWait.StatusCode) + } + }) + + if container.State.Running { + t.Fatalf("The container should be stopped after wait") } } -func testContainerWait(t *testing.T, srv *Server, id string) { - - r := httptest.NewRecorder() - - req, err := http.NewRequest("POST", "/containers/"+id+"/wait", nil) - req.Header.Set("Content-Type", "plain/text") - - if err != nil { - t.Fatal(err) - } - - body, err := postContainersWait(srv, r, req, nil) - if err != nil { - t.Fatal(err) - } - - if body == nil { - t.Fatalf("Body expected, received: nil\n") - } - - if r.Code != http.StatusOK { - t.Fatalf("%d OK expected, received %d\n", http.StatusNoContent, r.Code) - } +func TestPostContainersAttach(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") } // FIXME: Test deleting runnign container @@ -567,25 +726,7 @@ func TestDeleteContainers(t *testing.T) { } } -func testContainerChanges(t *testing.T, srv *Server, id string) { - - r := httptest.NewRecorder() - - req, err := http.NewRequest("GET", "/containers/"+id+"/changes", nil) - if err != nil { - t.Fatal(err) - } - - body, err := getContainersChanges(srv, r, req, nil) - if err != nil { - t.Fatal(err) - } - - if body == nil { - t.Fatalf("Body expected, received: nil\n") - } - - if r.Code != http.StatusOK { - t.Fatalf("%d OK expected, received %d\n", http.StatusNoContent, r.Code) - } +func TestDeleteImages(t *testing.T) { + //FIXME: Implement this test + t.Log("Test on implemented") }