diff --git a/components/engine/CHANGELOG.md b/components/engine/CHANGELOG.md index a8464b5345..44e52eecb5 100644 --- a/components/engine/CHANGELOG.md +++ b/components/engine/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.4.0 (2013-06-03) + + Introducing Builder: 'docker build' builds a container, layer by layer, from a source repository containing a Dockerfile + + Introducing Remote API: control Docker programmatically using a simple HTTP/json API + * Runtime: various reliability and usability improvements + ## 0.3.4 (2013-05-30) + Builder: 'docker build' builds a container, layer by layer, from a source repository containing a Dockerfile + Builder: 'docker build -t FOO' applies the tag FOO to the newly built container. diff --git a/components/engine/README.md b/components/engine/README.md index 918fdaade2..bcad502abc 100644 --- a/components/engine/README.md +++ b/components/engine/README.md @@ -251,7 +251,7 @@ Note ---- We also keep the documentation in this repository. The website documentation is generated using sphinx using these sources. -Please find it under docs/sources/ and read more about it https://github.com/dotcloud/docker/master/docs/README.md +Please find it under docs/sources/ and read more about it https://github.com/dotcloud/docker/tree/master/docs/README.md Please feel free to fix / update the documentation and send us pull requests. More tutorials are also welcome. @@ -371,4 +371,7 @@ Standard Container Specification #### Security +### Legal + +Transfers Docker shall be in accordance with any applicable export control or other legal requirements. diff --git a/components/engine/api.go b/components/engine/api.go index b8a9bf26fb..7b0fac3dfc 100644 --- a/components/engine/api.go +++ b/components/engine/api.go @@ -13,7 +13,7 @@ import ( "strings" ) -const API_VERSION = 1.1 +const APIVERSION = 1.1 func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) { conn, _, err := w.(http.Hijacker).Hijack() @@ -54,7 +54,7 @@ func httpError(w http.ResponseWriter, err error) { } } -func writeJson(w http.ResponseWriter, b []byte) { +func writeJSON(w http.ResponseWriter, b []byte) { w.Header().Set("Content-Type", "application/json") w.Write(b) } @@ -84,7 +84,7 @@ func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reques if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -113,11 +113,11 @@ func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Reque } if status != "" { - b, err := json.Marshal(&ApiAuth{Status: status}) + b, err := json.Marshal(&APIAuth{Status: status}) if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } w.WriteHeader(http.StatusNoContent) @@ -130,7 +130,7 @@ func getVersion(srv *Server, version float64, w http.ResponseWriter, r *http.Req if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -159,7 +159,7 @@ func getContainersExport(srv *Server, version float64, w http.ResponseWriter, r return nil } -func getImagesJson(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getImagesJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -178,7 +178,7 @@ func getImagesJson(srv *Server, version float64, w http.ResponseWriter, r *http. if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -195,7 +195,7 @@ func getInfo(srv *Server, version float64, w http.ResponseWriter, r *http.Reques if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -212,7 +212,7 @@ func getImagesHistory(srv *Server, version float64, w http.ResponseWriter, r *ht if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -229,11 +229,11 @@ func getContainersChanges(srv *Server, version float64, w http.ResponseWriter, r if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } -func getContainersJson(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { +func getContainersJSON(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } @@ -253,7 +253,7 @@ func getContainersJson(srv *Server, version float64, w http.ResponseWriter, r *h if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -296,12 +296,12 @@ func postCommit(srv *Server, version float64, w http.ResponseWriter, r *http.Req if err != nil { return err } - b, err := json.Marshal(&ApiId{id}) + b, err := json.Marshal(&APIID{id}) if err != nil { return err } w.WriteHeader(http.StatusCreated) - writeJson(w, b) + writeJSON(w, b) return nil } @@ -355,7 +355,7 @@ func getImagesSearch(srv *Server, version float64, w http.ResponseWriter, r *htt if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -374,18 +374,18 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht w.Header().Set("Content-Type", "application/json") } sf := utils.NewStreamFormatter(version > 1.0) - imgId, err := srv.ImageInsert(name, url, path, w, sf) + imgID, err := srv.ImageInsert(name, url, path, w, sf) if err != nil { if sf.Used() { w.Write(sf.FormatError(err)) return nil } } - b, err := json.Marshal(&ApiId{Id: imgId}) + b, err := json.Marshal(&APIID{ID: imgID}) if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -423,8 +423,8 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r return err } - out := &ApiRun{ - Id: id, + out := &APIRun{ + ID: id, } if config.Memory > 0 && !srv.runtime.capabilities.MemoryLimit { log.Println("WARNING: Your kernel does not support memory limit capabilities. Limitation discarded.") @@ -439,7 +439,7 @@ func postContainersCreate(srv *Server, version float64, w http.ResponseWriter, r return err } w.WriteHeader(http.StatusCreated) - writeJson(w, b) + writeJSON(w, b) return nil } @@ -500,7 +500,7 @@ func deleteImages(srv *Server, version float64, w http.ResponseWriter, r *http.R if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) } else { return fmt.Errorf("Conflict, %s wasn't deleted", name) } @@ -552,11 +552,11 @@ func postContainersWait(srv *Server, version float64, w http.ResponseWriter, r * if err != nil { return err } - b, err := json.Marshal(&ApiWait{StatusCode: status}) + b, err := json.Marshal(&APIWait{StatusCode: status}) if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -643,7 +643,7 @@ func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -661,17 +661,17 @@ func getImagesByName(srv *Server, version float64, w http.ResponseWriter, r *htt if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } func postImagesGetCache(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error { - apiConfig := &ApiImageConfig{} + apiConfig := &APIImageConfig{} if err := json.NewDecoder(r.Body).Decode(apiConfig); err != nil { return err } - image, err := srv.ImageGetCached(apiConfig.Id, apiConfig.Config) + image, err := srv.ImageGetCached(apiConfig.ID, apiConfig.Config) if err != nil { return err } @@ -679,12 +679,12 @@ func postImagesGetCache(srv *Server, version float64, w http.ResponseWriter, r * w.WriteHeader(http.StatusNotFound) return nil } - apiId := &ApiId{Id: image.Id} - b, err := json.Marshal(apiId) + apiID := &APIID{ID: image.ID} + b, err := json.Marshal(apiID) if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -730,13 +730,13 @@ func ListenAndServe(addr string, srv *Server, logging bool) error { "/auth": getAuth, "/version": getVersion, "/info": getInfo, - "/images/json": getImagesJson, + "/images/json": getImagesJSON, "/images/viz": getImagesViz, "/images/search": getImagesSearch, "/images/{name:.*}/history": getImagesHistory, "/images/{name:.*}/json": getImagesByName, - "/containers/ps": getContainersJson, - "/containers/json": getContainersJson, + "/containers/ps": getContainersJSON, + "/containers/json": getContainersJSON, "/containers/{name:.*}/export": getContainersExport, "/containers/{name:.*}/changes": getContainersChanges, "/containers/{name:.*}/json": getContainersByName, @@ -785,9 +785,9 @@ func ListenAndServe(addr string, srv *Server, logging bool) error { } version, err := strconv.ParseFloat(mux.Vars(r)["version"], 64) if err != nil { - version = API_VERSION + version = APIVERSION } - if version == 0 || version > API_VERSION { + if version == 0 || version > APIVERSION { w.WriteHeader(http.StatusNotFound) return } diff --git a/components/engine/api_params.go b/components/engine/api_params.go index 6f759f2d80..33b915cea5 100644 --- a/components/engine/api_params.go +++ b/components/engine/api_params.go @@ -1,35 +1,35 @@ package docker -type ApiHistory struct { - Id string +type APIHistory struct { + ID string `json:"Id"` Created int64 - CreatedBy string + CreatedBy string `json:",omitempty"` } -type ApiImages struct { +type APIImages struct { Repository string `json:",omitempty"` Tag string `json:",omitempty"` - Id string + ID string `json:"Id"` Created int64 } -type ApiInfo struct { - Containers int - Version string - Images int +type APIInfo struct { Debug bool - GoVersion string - NFd int `json:",omitempty"` - NGoroutines int `json:",omitempty"` + Containers int + Images int + NFd int `json:",omitempty"` + NGoroutines int `json:",omitempty"` + MemoryLimit bool `json:",omitempty"` + SwapLimit bool `json:",omitempty"` } -type ApiRmi struct { +type APIRmi struct { Deleted string `json:",omitempty"` Untagged string `json:",omitempty"` } -type ApiContainers struct { - Id string +type APIContainers struct { + ID string `json:"Id"` Image string Command string Created int64 @@ -37,40 +37,39 @@ type ApiContainers struct { Ports string } -type ApiSearch struct { +type APISearch struct { Name string Description string } -type ApiId struct { - Id string +type APIID struct { + ID string `json:"Id"` } -type ApiRun struct { - Id string - Warnings []string +type APIRun struct { + ID string `json:"Id"` + Warnings []string `json:",omitempty"` } -type ApiPort struct { +type APIPort struct { Port string } -type ApiVersion struct { - Version string - GitCommit string - MemoryLimit bool - SwapLimit bool +type APIVersion struct { + Version string + GitCommit string `json:",omitempty"` + GoVersion string `json:",omitempty"` } -type ApiWait struct { +type APIWait struct { StatusCode int } -type ApiAuth struct { +type APIAuth struct { Status string } -type ApiImageConfig struct { - Id string +type APIImageConfig struct { + ID string `json:"Id"` *Config } diff --git a/components/engine/api_test.go b/components/engine/api_test.go index 20f707e3c1..5b1938bd28 100644 --- a/components/engine/api_test.go +++ b/components/engine/api_test.go @@ -37,17 +37,17 @@ func TestGetAuth(t *testing.T) { Email: "utest@yopmail.com", } - authConfigJson, err := json.Marshal(authConfig) + authConfigJSON, err := json.Marshal(authConfig) if err != nil { t.Fatal(err) } - req, err := http.NewRequest("POST", "/auth", bytes.NewReader(authConfigJson)) + req, err := http.NewRequest("POST", "/auth", bytes.NewReader(authConfigJSON)) if err != nil { t.Fatal(err) } - if err := postAuth(srv, API_VERSION, r, req, nil); err != nil { + if err := postAuth(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } @@ -73,11 +73,11 @@ func TestGetVersion(t *testing.T) { r := httptest.NewRecorder() - if err := getVersion(srv, API_VERSION, r, nil, nil); err != nil { + if err := getVersion(srv, APIVERSION, r, nil, nil); err != nil { t.Fatal(err) } - v := &ApiVersion{} + v := &APIVersion{} if err = json.Unmarshal(r.Body.Bytes(), v); err != nil { t.Fatal(err) } @@ -97,21 +97,21 @@ func TestGetInfo(t *testing.T) { r := httptest.NewRecorder() - if err := getInfo(srv, API_VERSION, r, nil, nil); err != nil { + if err := getInfo(srv, APIVERSION, r, nil, nil); err != nil { t.Fatal(err) } - infos := &ApiInfo{} + infos := &APIInfo{} err = json.Unmarshal(r.Body.Bytes(), infos) if err != nil { t.Fatal(err) } - if infos.Version != VERSION { - t.Errorf("Excepted version %s, %s found", VERSION, infos.Version) + if infos.Images != 1 { + t.Errorf("Excepted images: %d, %d found", 1, infos.Images) } } -func TestGetImagesJson(t *testing.T) { +func TestGetImagesJSON(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -128,11 +128,11 @@ func TestGetImagesJson(t *testing.T) { r := httptest.NewRecorder() - if err := getImagesJson(srv, API_VERSION, r, req, nil); err != nil { + if err := getImagesJSON(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } - images := []ApiImages{} + images := []APIImages{} if err := json.Unmarshal(r.Body.Bytes(), &images); err != nil { t.Fatal(err) } @@ -153,11 +153,11 @@ func TestGetImagesJson(t *testing.T) { t.Fatal(err) } - if err := getImagesJson(srv, API_VERSION, r2, req2, nil); err != nil { + if err := getImagesJSON(srv, APIVERSION, r2, req2, nil); err != nil { t.Fatal(err) } - images2 := []ApiImages{} + images2 := []APIImages{} if err := json.Unmarshal(r2.Body.Bytes(), &images2); err != nil { t.Fatal(err) } @@ -166,8 +166,8 @@ func TestGetImagesJson(t *testing.T) { t.Errorf("Excepted 1 image, %d found", len(images2)) } - if images2[0].Id != GetTestImage(runtime).Id { - t.Errorf("Retrieved image Id differs, expected %s, received %s", GetTestImage(runtime).Id, images2[0].Id) + if images2[0].ID != GetTestImage(runtime).ID { + t.Errorf("Retrieved image Id differs, expected %s, received %s", GetTestImage(runtime).ID, images2[0].ID) } r3 := httptest.NewRecorder() @@ -178,11 +178,11 @@ func TestGetImagesJson(t *testing.T) { t.Fatal(err) } - if err := getImagesJson(srv, API_VERSION, r3, req3, nil); err != nil { + if err := getImagesJSON(srv, APIVERSION, r3, req3, nil); err != nil { t.Fatal(err) } - images3 := []ApiImages{} + images3 := []APIImages{} if err := json.Unmarshal(r3.Body.Bytes(), &images3); err != nil { t.Fatal(err) } @@ -199,7 +199,7 @@ func TestGetImagesJson(t *testing.T) { t.Fatal(err) } - err = getImagesJson(srv, API_VERSION, r4, req4, nil) + err = getImagesJSON(srv, APIVERSION, r4, req4, nil) if err == nil { t.Fatalf("Error expected, received none") } @@ -220,7 +220,7 @@ func TestGetImagesViz(t *testing.T) { srv := &Server{runtime: runtime} r := httptest.NewRecorder() - if err := getImagesViz(srv, API_VERSION, r, nil, nil); err != nil { + if err := getImagesViz(srv, APIVERSION, r, nil, nil); err != nil { t.Fatal(err) } @@ -256,11 +256,11 @@ func TestGetImagesSearch(t *testing.T) { t.Fatal(err) } - if err := getImagesSearch(srv, API_VERSION, r, req, nil); err != nil { + if err := getImagesSearch(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } - results := []ApiSearch{} + results := []APISearch{} if err := json.Unmarshal(r.Body.Bytes(), &results); err != nil { t.Fatal(err) } @@ -280,11 +280,11 @@ func TestGetImagesHistory(t *testing.T) { r := httptest.NewRecorder() - if err := getImagesHistory(srv, API_VERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { + if err := getImagesHistory(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { t.Fatal(err) } - history := []ApiHistory{} + history := []APIHistory{} if err := json.Unmarshal(r.Body.Bytes(), &history); err != nil { t.Fatal(err) } @@ -303,7 +303,7 @@ func TestGetImagesByName(t *testing.T) { srv := &Server{runtime: runtime} r := httptest.NewRecorder() - if err := getImagesByName(srv, API_VERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { + if err := getImagesByName(srv, APIVERSION, r, nil, map[string]string{"name": unitTestImageName}); err != nil { t.Fatal(err) } @@ -311,12 +311,12 @@ func TestGetImagesByName(t *testing.T) { if err := json.Unmarshal(r.Body.Bytes(), img); err != nil { t.Fatal(err) } - if img.Id != GetTestImage(runtime).Id || img.Comment != "Imported from http://get.docker.io/images/busybox" { + if img.ID != GetTestImage(runtime).ID || img.Comment != "Imported from http://get.docker.io/images/busybox" { t.Errorf("Error inspecting image") } } -func TestGetContainersJson(t *testing.T) { +func TestGetContainersJSON(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -326,7 +326,7 @@ func TestGetContainersJson(t *testing.T) { srv := &Server{runtime: runtime} container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "test"}, }) if err != nil { @@ -340,18 +340,18 @@ func TestGetContainersJson(t *testing.T) { } r := httptest.NewRecorder() - if err := getContainersJson(srv, API_VERSION, r, req, nil); err != nil { + if err := getContainersJSON(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } - containers := []ApiContainers{} + containers := []APIContainers{} if err := json.Unmarshal(r.Body.Bytes(), &containers); err != nil { t.Fatal(err) } if len(containers) != 1 { t.Fatalf("Excepted %d container, %d found", 1, len(containers)) } - if containers[0].Id != container.Id { - t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.Id, containers[0].Id) + if containers[0].ID != container.ID { + t.Fatalf("Container ID mismatch. Expected: %s, received: %s\n", container.ID, containers[0].ID) } } @@ -369,7 +369,7 @@ func TestGetContainersExport(t *testing.T) { // Create a container and remove a file container, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, }, ) @@ -383,7 +383,7 @@ func TestGetContainersExport(t *testing.T) { } r := httptest.NewRecorder() - if err = getContainersExport(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err = getContainersExport(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } @@ -424,7 +424,7 @@ func TestGetContainersChanges(t *testing.T) { // Create a container and remove a file container, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/rm", "/etc/passwd"}, }, ) @@ -438,7 +438,7 @@ func TestGetContainersChanges(t *testing.T) { } r := httptest.NewRecorder() - if err := getContainersChanges(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err := getContainersChanges(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } changes := []Change{} @@ -472,7 +472,7 @@ func TestGetContainersByName(t *testing.T) { // Create a container and remove a file container, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "test"}, }, ) @@ -482,15 +482,15 @@ func TestGetContainersByName(t *testing.T) { defer runtime.Destroy(container) r := httptest.NewRecorder() - if err := getContainersByName(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err := getContainersByName(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } outContainer := &Container{} if err := json.Unmarshal(r.Body.Bytes(), outContainer); err != nil { t.Fatal(err) } - if outContainer.Id != container.Id { - t.Fatalf("Wrong containers retrieved. Expected %s, recieved %s", container.Id, outContainer.Id) + if outContainer.ID != container.ID { + t.Fatalf("Wrong containers retrieved. Expected %s, recieved %s", container.ID, outContainer.ID) } } @@ -514,7 +514,7 @@ func TestPostAuth(t *testing.T) { auth.SaveConfig(runtime.root, authStr, config.Email) r := httptest.NewRecorder() - if err := getAuth(srv, API_VERSION, r, nil, nil); err != nil { + if err := getAuth(srv, APIVERSION, r, nil, nil); err != nil { t.Fatal(err) } @@ -542,7 +542,7 @@ func TestPostCommit(t *testing.T) { // Create a container and remove a file container, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, }, ) @@ -555,24 +555,24 @@ func TestPostCommit(t *testing.T) { t.Fatal(err) } - req, err := http.NewRequest("POST", "/commit?repo=testrepo&testtag=tag&container="+container.Id, bytes.NewReader([]byte{})) + req, err := http.NewRequest("POST", "/commit?repo=testrepo&testtag=tag&container="+container.ID, bytes.NewReader([]byte{})) if err != nil { t.Fatal(err) } r := httptest.NewRecorder() - if err := postCommit(srv, API_VERSION, r, req, nil); err != nil { + if err := postCommit(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } if r.Code != http.StatusCreated { t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code) } - apiId := &ApiId{} - if err := json.Unmarshal(r.Body.Bytes(), apiId); err != nil { + apiID := &APIID{} + if err := json.Unmarshal(r.Body.Bytes(), apiID); err != nil { t.Fatal(err) } - if _, err := runtime.graph.Get(apiId.Id); err != nil { + if _, err := runtime.graph.Get(apiID.ID); err != nil { t.Fatalf("The image has not been commited") } } @@ -715,7 +715,7 @@ func TestPostImagesInsert(t *testing.T) { // t.Fatalf("The test file has not been found") // } - // if err := srv.runtime.graph.Delete(img.Id); err != nil { + // if err := srv.runtime.graph.Delete(img.ID); err != nil { // t.Fatal(err) // } } @@ -824,8 +824,8 @@ func TestPostContainersCreate(t *testing.T) { srv := &Server{runtime: runtime} - configJson, err := json.Marshal(&Config{ - Image: GetTestImage(runtime).Id, + configJSON, err := json.Marshal(&Config{ + Image: GetTestImage(runtime).ID, Memory: 33554432, Cmd: []string{"touch", "/test"}, }) @@ -833,25 +833,25 @@ func TestPostContainersCreate(t *testing.T) { t.Fatal(err) } - req, err := http.NewRequest("POST", "/containers/create", bytes.NewReader(configJson)) + req, err := http.NewRequest("POST", "/containers/create", bytes.NewReader(configJSON)) if err != nil { t.Fatal(err) } r := httptest.NewRecorder() - if err := postContainersCreate(srv, API_VERSION, r, req, nil); err != nil { + if err := postContainersCreate(srv, APIVERSION, r, req, nil); err != nil { t.Fatal(err) } if r.Code != http.StatusCreated { t.Fatalf("%d Created expected, received %d\n", http.StatusCreated, r.Code) } - apiRun := &ApiRun{} + apiRun := &APIRun{} if err := json.Unmarshal(r.Body.Bytes(), apiRun); err != nil { t.Fatal(err) } - container := srv.runtime.Get(apiRun.Id) + container := srv.runtime.Get(apiRun.ID) if container == nil { t.Fatalf("Container not created") } @@ -880,7 +880,7 @@ func TestPostContainersKill(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -902,7 +902,7 @@ func TestPostContainersKill(t *testing.T) { } r := httptest.NewRecorder() - if err := postContainersKill(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err := postContainersKill(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } if r.Code != http.StatusNoContent { @@ -924,7 +924,7 @@ func TestPostContainersRestart(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -945,12 +945,12 @@ func TestPostContainersRestart(t *testing.T) { t.Errorf("Container should be running") } - req, err := http.NewRequest("POST", "/containers/"+container.Id+"/restart?t=1", bytes.NewReader([]byte{})) + req, err := http.NewRequest("POST", "/containers/"+container.ID+"/restart?t=1", bytes.NewReader([]byte{})) if err != nil { t.Fatal(err) } r := httptest.NewRecorder() - if err := postContainersRestart(srv, API_VERSION, r, req, map[string]string{"name": container.Id}); err != nil { + if err := postContainersRestart(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } if r.Code != http.StatusNoContent { @@ -980,7 +980,7 @@ func TestPostContainersStart(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -991,7 +991,7 @@ func TestPostContainersStart(t *testing.T) { defer runtime.Destroy(container) r := httptest.NewRecorder() - if err := postContainersStart(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err := postContainersStart(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } if r.Code != http.StatusNoContent { @@ -1006,7 +1006,7 @@ func TestPostContainersStart(t *testing.T) { } r = httptest.NewRecorder() - if err = postContainersStart(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err == nil { + if err = postContainersStart(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err == nil { t.Fatalf("A running containter should be able to be started") } @@ -1026,7 +1026,7 @@ func TestPostContainersStop(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -1048,12 +1048,12 @@ func TestPostContainersStop(t *testing.T) { } // Note: as it is a POST request, it requires a body. - req, err := http.NewRequest("POST", "/containers/"+container.Id+"/stop?t=1", bytes.NewReader([]byte{})) + req, err := http.NewRequest("POST", "/containers/"+container.ID+"/stop?t=1", bytes.NewReader([]byte{})) if err != nil { t.Fatal(err) } r := httptest.NewRecorder() - if err := postContainersStop(srv, API_VERSION, r, req, map[string]string{"name": container.Id}); err != nil { + if err := postContainersStop(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } if r.Code != http.StatusNoContent { @@ -1075,7 +1075,7 @@ func TestPostContainersWait(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sleep", "1"}, OpenStdin: true, }, @@ -1091,10 +1091,10 @@ func TestPostContainersWait(t *testing.T) { setTimeout(t, "Wait timed out", 3*time.Second, func() { r := httptest.NewRecorder() - if err := postContainersWait(srv, API_VERSION, r, nil, map[string]string{"name": container.Id}); err != nil { + if err := postContainersWait(srv, APIVERSION, r, nil, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } - apiWait := &ApiWait{} + apiWait := &APIWait{} if err := json.Unmarshal(r.Body.Bytes(), apiWait); err != nil { t.Fatal(err) } @@ -1119,7 +1119,7 @@ func TestPostContainersAttach(t *testing.T) { container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -1148,12 +1148,12 @@ func TestPostContainersAttach(t *testing.T) { out: stdoutPipe, } - req, err := http.NewRequest("POST", "/containers/"+container.Id+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{})) + req, err := http.NewRequest("POST", "/containers/"+container.ID+"/attach?stream=1&stdin=1&stdout=1&stderr=1", bytes.NewReader([]byte{})) if err != nil { t.Fatal(err) } - if err := postContainersAttach(srv, API_VERSION, r, req, map[string]string{"name": container.Id}); err != nil { + if err := postContainersAttach(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } }() @@ -1206,7 +1206,7 @@ func TestDeleteContainers(t *testing.T) { srv := &Server{runtime: runtime} container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"touch", "/test"}, }) if err != nil { @@ -1218,19 +1218,19 @@ func TestDeleteContainers(t *testing.T) { t.Fatal(err) } - req, err := http.NewRequest("DELETE", "/containers/"+container.Id, nil) + req, err := http.NewRequest("DELETE", "/containers/"+container.ID, nil) if err != nil { t.Fatal(err) } r := httptest.NewRecorder() - if err := deleteContainers(srv, API_VERSION, r, req, map[string]string{"name": container.Id}); err != nil { + if err := deleteContainers(srv, APIVERSION, r, req, map[string]string{"name": container.ID}); err != nil { t.Fatal(err) } if r.Code != http.StatusNoContent { t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code) } - if c := runtime.Get(container.Id); c != nil { + if c := runtime.Get(container.ID); c != nil { t.Fatalf("The container as not been deleted") } @@ -1267,14 +1267,14 @@ func TestDeleteImages(t *testing.T) { } r := httptest.NewRecorder() - if err := deleteImages(srv, API_VERSION, r, req, map[string]string{"name": "test:test"}); err != nil { + if err := deleteImages(srv, APIVERSION, r, req, map[string]string{"name": "test:test"}); err != nil { t.Fatal(err) } if r.Code != http.StatusOK { t.Fatalf("%d OK expected, received %d\n", http.StatusOK, r.Code) } - var outs []ApiRmi + var outs []APIRmi if err := json.Unmarshal(r.Body.Bytes(), &outs); err != nil { t.Fatal(err) } diff --git a/components/engine/auth/auth.go b/components/engine/auth/auth.go index 9c34604419..72cf36efa5 100644 --- a/components/engine/auth/auth.go +++ b/components/engine/auth/auth.go @@ -16,12 +16,12 @@ import ( const CONFIGFILE = ".dockercfg" // the registry server we want to login against -const INDEX_SERVER = "https://index.docker.io/v1" +const INDEXSERVER = "https://index.docker.io/v1" -//const INDEX_SERVER = "http://indexstaging-docker.dotcloud.com/" +//const INDEXSERVER = "http://indexstaging-docker.dotcloud.com/" var ( - ErrConfigFileMissing error = errors.New("The Auth config file is missing") + ErrConfigFileMissing = errors.New("The Auth config file is missing") ) type AuthConfig struct { @@ -44,7 +44,7 @@ func IndexServerAddress() string { if os.Getenv("DOCKER_INDEX_URL") != "" { return os.Getenv("DOCKER_INDEX_URL") + "/v1" } - return INDEX_SERVER + return INDEXSERVER } // create a base64 encoded auth string to store in config diff --git a/components/engine/builder.go b/components/engine/builder.go index 5f56f65d05..808b7efcab 100644 --- a/components/engine/builder.go +++ b/components/engine/builder.go @@ -40,7 +40,7 @@ func (builder *Builder) Create(config *Config) (*Container, error) { } // Generate id - id := GenerateId() + id := GenerateID() // Generate default hostname // FIXME: the lxc template no longer needs to set a default hostname if config.Hostname == "" { @@ -49,17 +49,17 @@ func (builder *Builder) Create(config *Config) (*Container, error) { container := &Container{ // FIXME: we should generate the ID here instead of receiving it as an argument - Id: id, + ID: id, Created: time.Now(), Path: config.Cmd[0], Args: config.Cmd[1:], //FIXME: de-duplicate from config Config: config, - Image: img.Id, // Always use the resolved image id + Image: img.ID, // Always use the resolved image id NetworkSettings: &NetworkSettings{}, // FIXME: do we need to store this in the container? SysInitPath: sysInitPath, } - container.root = builder.runtime.containerRoot(container.Id) + container.root = builder.runtime.containerRoot(container.ID) // Step 1: create the container directory. // This doubles as a barrier to avoid race conditions. if err := os.Mkdir(container.root, 0700); err != nil { @@ -110,7 +110,7 @@ func (builder *Builder) Commit(container *Container, repository, tag, comment, a } // Register the image if needed if repository != "" { - if err := builder.repositories.Set(repository, tag, img.Id, true); err != nil { + if err := builder.repositories.Set(repository, tag, img.ID, true); err != nil { return img, err } } diff --git a/components/engine/builder_client.go b/components/engine/builder_client.go index 144e11b415..dc9528ff41 100644 --- a/components/engine/builder_client.go +++ b/components/engine/builder_client.go @@ -63,11 +63,11 @@ func (b *builderClient) CmdFrom(name string) error { return err } - img := &ApiId{} + img := &APIID{} if err := json.Unmarshal(obj, img); err != nil { return err } - b.image = img.Id + b.image = img.ID utils.Debugf("Using image %s", b.image) return nil } @@ -91,19 +91,19 @@ func (b *builderClient) CmdRun(args string) error { b.config.Cmd = nil MergeConfig(b.config, config) - body, statusCode, err := b.cli.call("POST", "/images/getCache", &ApiImageConfig{Id: b.image, Config: b.config}) + body, statusCode, err := b.cli.call("POST", "/images/getCache", &APIImageConfig{ID: b.image, Config: b.config}) if err != nil { if statusCode != 404 { return err } } if statusCode != 404 { - apiId := &ApiId{} - if err := json.Unmarshal(body, apiId); err != nil { + apiID := &APIID{} + if err := json.Unmarshal(body, apiID); err != nil { return err } utils.Debugf("Use cached version") - b.image = apiId.Id + b.image = apiID.ID return nil } cid, err := b.run() @@ -163,7 +163,7 @@ func (b *builderClient) CmdInsert(args string) error { // return err // } - // apiId := &ApiId{} + // apiId := &APIId{} // if err := json.Unmarshal(body, apiId); err != nil { // return err // } @@ -182,7 +182,7 @@ func (b *builderClient) run() (string, error) { return "", err } - apiRun := &ApiRun{} + apiRun := &APIRun{} if err := json.Unmarshal(body, apiRun); err != nil { return "", err } @@ -191,18 +191,18 @@ func (b *builderClient) run() (string, error) { } //start the container - _, _, err = b.cli.call("POST", "/containers/"+apiRun.Id+"/start", nil) + _, _, err = b.cli.call("POST", "/containers/"+apiRun.ID+"/start", nil) if err != nil { return "", err } - b.tmpContainers[apiRun.Id] = struct{}{} + b.tmpContainers[apiRun.ID] = struct{}{} // Wait for it to finish - body, _, err = b.cli.call("POST", "/containers/"+apiRun.Id+"/wait", nil) + body, _, err = b.cli.call("POST", "/containers/"+apiRun.ID+"/wait", nil) if err != nil { return "", err } - apiWait := &ApiWait{} + apiWait := &APIWait{} if err := json.Unmarshal(body, apiWait); err != nil { return "", err } @@ -210,7 +210,7 @@ func (b *builderClient) run() (string, error) { return "", fmt.Errorf("The command %v returned a non-zero code: %d", b.config.Cmd, apiWait.StatusCode) } - return apiRun.Id, nil + return apiRun.ID, nil } func (b *builderClient) commit(id string) error { @@ -222,11 +222,11 @@ func (b *builderClient) commit(id string) error { if id == "" { cmd := b.config.Cmd b.config.Cmd = []string{"true"} - if cid, err := b.run(); err != nil { + cid, err := b.run() + if err != nil { return err - } else { - id = cid } + id = cid b.config.Cmd = cmd } @@ -239,12 +239,12 @@ func (b *builderClient) commit(id string) error { if err != nil { return err } - apiId := &ApiId{} - if err := json.Unmarshal(body, apiId); err != nil { + apiID := &APIID{} + if err := json.Unmarshal(body, apiID); err != nil { return err } - b.tmpImages[apiId.Id] = struct{}{} - b.image = apiId.Id + b.tmpImages[apiID.ID] = struct{}{} + b.image = apiID.ID b.needCommit = false return nil } diff --git a/components/engine/buildfile.go b/components/engine/buildfile.go index a015830e0d..5ea5607fc7 100644 --- a/components/engine/buildfile.go +++ b/components/engine/buildfile.go @@ -73,7 +73,7 @@ func (b *buildFile) CmdFrom(name string) error { return err } } - b.image = image.Id + b.image = image.ID b.config = &Config{} return nil } @@ -102,7 +102,7 @@ func (b *buildFile) CmdRun(args string) error { return err } else if cache != nil { utils.Debugf("[BUILDER] Use cached version") - b.image = cache.Id + b.image = cache.ID return nil } else { utils.Debugf("[BUILDER] Cache miss") @@ -238,7 +238,7 @@ func (b *buildFile) run() (string, error) { if err != nil { return "", err } - b.tmpContainers[c.Id] = struct{}{} + b.tmpContainers[c.ID] = struct{}{} //start the container if err := c.Start(); err != nil { @@ -250,7 +250,7 @@ func (b *buildFile) run() (string, error) { return "", fmt.Errorf("The command %v returned a non-zero code: %d", b.config.Cmd, ret) } - return c.Id, nil + return c.ID, nil } // Commit the container with the autorun command @@ -266,17 +266,17 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { return err } else if cache != nil { utils.Debugf("[BUILDER] Use cached version") - b.image = cache.Id + b.image = cache.ID return nil } else { utils.Debugf("[BUILDER] Cache miss") } - if cid, err := b.run(); err != nil { + cid, err := b.run() + if err != nil { return err - } else { - id = cid } + id = cid } container := b.runtime.Get(id) @@ -292,8 +292,8 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { if err != nil { return err } - b.tmpImages[image.Id] = struct{}{} - b.image = image.Id + b.tmpImages[image.ID] = struct{}{} + b.image = image.ID return nil } diff --git a/components/engine/buildfile_test.go b/components/engine/buildfile_test.go index b6f4e62ae9..ffbcdbbddc 100644 --- a/components/engine/buildfile_test.go +++ b/components/engine/buildfile_test.go @@ -26,7 +26,7 @@ func TestBuild(t *testing.T) { buildfile := NewBuildFile(srv, &utils.NopWriter{}) - imgId, err := buildfile.Build(strings.NewReader(Dockerfile), nil) + imgID, err := buildfile.Build(strings.NewReader(Dockerfile), nil) if err != nil { t.Fatal(err) } @@ -34,7 +34,7 @@ func TestBuild(t *testing.T) { builder := NewBuilder(runtime) container, err := builder.Create( &Config{ - Image: imgId, + Image: imgID, Cmd: []string{"cat", "/tmp/passwd"}, }, ) @@ -53,7 +53,7 @@ func TestBuild(t *testing.T) { container2, err := builder.Create( &Config{ - Image: imgId, + Image: imgID, Cmd: []string{"ls", "-d", "/var/run/sshd"}, }, ) diff --git a/components/engine/changes.go b/components/engine/changes.go index 4c79918887..dc1b015726 100644 --- a/components/engine/changes.go +++ b/components/engine/changes.go @@ -65,7 +65,7 @@ func Changes(layers []string, rw string) ([]Change, error) { file := filepath.Base(path) // If there is a whiteout, then the file was removed if strings.HasPrefix(file, ".wh.") { - originalFile := strings.TrimLeft(file, ".wh.") + originalFile := file[len(".wh."):] change.Path = filepath.Join(filepath.Dir(path), originalFile) change.Kind = ChangeDelete } else { diff --git a/components/engine/commands.go b/components/engine/commands.go index 16746bfe65..514fee50a9 100644 --- a/components/engine/commands.go +++ b/components/engine/commands.go @@ -28,10 +28,10 @@ import ( "unicode" ) -const VERSION = "0.3.4" +const VERSION = "0.4.0" var ( - GIT_COMMIT string + GITCOMMIT string ) func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) { @@ -159,11 +159,11 @@ func (cli *DockerCli) CmdBuild(args ...string) error { file = os.Stdin } else { // Send Dockerfile from arg/Dockerfile (deprecate later) - if f, err := os.Open(path.Join(cmd.Arg(0), "Dockerfile")); err != nil { + f, err := os.Open(path.Join(cmd.Arg(0), "Dockerfile")) + if err != nil { return err - } else { - file = f } + file = f // Send context from arg // Create a FormFile multipart for the context if needed // FIXME: Use NewTempArchive in order to have the size and avoid too much memory usage? @@ -176,21 +176,21 @@ func (cli *DockerCli) CmdBuild(args ...string) error { if err != nil { return err } - if wField, err := w.CreateFormFile("Context", filepath.Base(absPath)+"."+compression.Extension()); err != nil { + wField, err := w.CreateFormFile("Context", filepath.Base(absPath)+"."+compression.Extension()) + if err != nil { return err - } else { - // FIXME: Find a way to have a progressbar for the upload too - sf := utils.NewStreamFormatter(false) - io.Copy(wField, utils.ProgressReader(ioutil.NopCloser(context), -1, os.Stdout, sf.FormatProgress("Caching Context", "%v/%v (%v)"), sf)) } + // FIXME: Find a way to have a progressbar for the upload too + sf := utils.NewStreamFormatter(false) + io.Copy(wField, utils.ProgressReader(ioutil.NopCloser(context), -1, os.Stdout, sf.FormatProgress("Caching Context", "%v/%v (%v)"), sf)) multipartBody = io.MultiReader(multipartBody, boundary) } // Create a FormFile multipart for the Dockerfile - if wField, err := w.CreateFormFile("Dockerfile", "Dockerfile"); err != nil { + wField, err := w.CreateFormFile("Dockerfile", "Dockerfile") + if err != nil { return err - } else { - io.Copy(wField, file) } + io.Copy(wField, file) multipartBody = io.MultiReader(multipartBody, boundary) v := &url.Values{} @@ -276,9 +276,8 @@ func (cli *DockerCli) CmdLogin(args ...string) error { oldState, err := term.SetRawTerminal() if err != nil { return err - } else { - defer term.RestoreTerminal(oldState) } + defer term.RestoreTerminal(oldState) cmd := Subcmd("login", "", "Register or Login to the docker registry server") if err := cmd.Parse(args); err != nil { @@ -331,7 +330,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error { return err } - var out2 ApiAuth + var out2 APIAuth err = json.Unmarshal(body, &out2) if err != nil { return err @@ -358,7 +357,7 @@ func (cli *DockerCli) CmdWait(args ...string) error { if err != nil { fmt.Printf("%s", err) } else { - var out ApiWait + var out APIWait err = json.Unmarshal(body, &out) if err != nil { return err @@ -386,21 +385,20 @@ func (cli *DockerCli) CmdVersion(args ...string) error { return err } - var out ApiVersion + var out APIVersion err = json.Unmarshal(body, &out) if err != nil { utils.Debugf("Error unmarshal: body: %s, err: %s\n", body, err) return err } - fmt.Println("Version:", out.Version) - fmt.Println("Git Commit:", out.GitCommit) - if !out.MemoryLimit { - fmt.Println("WARNING: No memory limit support") + fmt.Println("Client version:", VERSION) + fmt.Println("Server version:", out.Version) + if out.GitCommit != "" { + fmt.Println("Git commit:", out.GitCommit) } - if !out.SwapLimit { - fmt.Println("WARNING: No swap limit support") + if out.GoVersion != "" { + fmt.Println("Go version:", out.GoVersion) } - return nil } @@ -420,15 +418,24 @@ func (cli *DockerCli) CmdInfo(args ...string) error { return err } - var out ApiInfo - err = json.Unmarshal(body, &out) - if err != nil { + var out APIInfo + if err := json.Unmarshal(body, &out); err != nil { return err } - fmt.Printf("containers: %d\nversion: %s\nimages: %d\nGo version: %s\n", out.Containers, out.Version, out.Images, out.GoVersion) - if out.Debug { - fmt.Println("debug mode enabled") - fmt.Printf("fds: %d\ngoroutines: %d\n", out.NFd, out.NGoroutines) + + fmt.Printf("Containers: %d\n", out.Containers) + fmt.Printf("Images: %d\n", out.Images) + if out.Debug || os.Getenv("DEBUG") != "" { + fmt.Printf("Debug mode (server): %v\n", out.Debug) + fmt.Printf("Debug mode (client): %v\n", os.Getenv("DEBUG") != "") + fmt.Printf("Fds: %d\n", out.NFd) + fmt.Printf("Goroutines: %d\n", out.NGoroutines) + } + if !out.MemoryLimit { + fmt.Println("WARNING: No memory limit support") + } + if !out.SwapLimit { + fmt.Println("WARNING: No swap limit support") } return nil } @@ -575,7 +582,7 @@ func (cli *DockerCli) CmdRmi(args ...string) error { if err != nil { fmt.Fprintf(os.Stderr, "%s", err) } else { - var outs []ApiRmi + var outs []APIRmi err = json.Unmarshal(body, &outs) if err != nil { return err @@ -607,7 +614,7 @@ func (cli *DockerCli) CmdHistory(args ...string) error { return err } - var outs []ApiHistory + var outs []APIHistory err = json.Unmarshal(body, &outs) if err != nil { return err @@ -616,7 +623,7 @@ func (cli *DockerCli) CmdHistory(args ...string) error { fmt.Fprintln(w, "ID\tCREATED\tCREATED BY") for _, out := range outs { - fmt.Fprintf(w, "%s\t%s ago\t%s\n", out.Id, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.CreatedBy) + fmt.Fprintf(w, "%s\t%s ago\t%s\n", out.ID, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.CreatedBy) } w.Flush() return nil @@ -742,12 +749,6 @@ func (cli *DockerCli) CmdPull(args ...string) error { remote = remoteParts[0] } - if strings.Contains(remote, "/") { - if _, err := cli.checkIfLogged(true, "pull"); err != nil { - return err - } - } - v := url.Values{} v.Set("fromImage", remote) v.Set("tag", *tag) @@ -795,7 +796,7 @@ func (cli *DockerCli) CmdImages(args ...string) error { return err } - var outs []ApiImages + var outs []APIImages err = json.Unmarshal(body, &outs) if err != nil { return err @@ -817,16 +818,16 @@ func (cli *DockerCli) CmdImages(args ...string) error { if !*quiet { fmt.Fprintf(w, "%s\t%s\t", out.Repository, out.Tag) if *noTrunc { - fmt.Fprintf(w, "%s\t", out.Id) + fmt.Fprintf(w, "%s\t", out.ID) } else { - fmt.Fprintf(w, "%s\t", utils.TruncateId(out.Id)) + fmt.Fprintf(w, "%s\t", utils.TruncateID(out.ID)) } fmt.Fprintf(w, "%s ago\n", utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0)))) } else { if *noTrunc { - fmt.Fprintln(w, out.Id) + fmt.Fprintln(w, out.ID) } else { - fmt.Fprintln(w, utils.TruncateId(out.Id)) + fmt.Fprintln(w, utils.TruncateID(out.ID)) } } } @@ -873,7 +874,7 @@ func (cli *DockerCli) CmdPs(args ...string) error { return err } - var outs []ApiContainers + var outs []APIContainers err = json.Unmarshal(body, &outs) if err != nil { return err @@ -886,15 +887,15 @@ func (cli *DockerCli) CmdPs(args ...string) error { for _, out := range outs { if !*quiet { if *noTrunc { - fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", out.Id, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) + fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", out.ID, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) } else { - fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", utils.TruncateId(out.Id), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) + fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", utils.TruncateID(out.ID), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) } } else { if *noTrunc { - fmt.Fprintln(w, out.Id) + fmt.Fprintln(w, out.ID) } else { - fmt.Fprintln(w, utils.TruncateId(out.Id)) + fmt.Fprintln(w, utils.TruncateID(out.ID)) } } } @@ -937,13 +938,13 @@ func (cli *DockerCli) CmdCommit(args ...string) error { return err } - apiId := &ApiId{} - err = json.Unmarshal(body, apiId) + apiID := &APIID{} + err = json.Unmarshal(body, apiID) if err != nil { return err } - fmt.Println(apiId.Id) + fmt.Println(apiID.ID) return nil } @@ -1080,7 +1081,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error { return err } - outs := []ApiSearch{} + outs := []APISearch{} err = json.Unmarshal(body, &outs) if err != nil { return err @@ -1212,7 +1213,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { return err } - out := &ApiRun{} + out := &APIRun{} err = json.Unmarshal(body, out) if err != nil { return err @@ -1233,18 +1234,21 @@ func (cli *DockerCli) CmdRun(args ...string) error { } //start the container - _, _, err = cli.call("POST", "/containers/"+out.Id+"/start", nil) + _, _, err = cli.call("POST", "/containers/"+out.ID+"/start", nil) if err != nil { return err } + if !config.AttachStdout && !config.AttachStderr { + fmt.Println(out.ID) + } if connections > 0 { chErrors := make(chan error, connections) - cli.monitorTtySize(out.Id) + cli.monitorTtySize(out.ID) if splitStderr && config.AttachStderr { go func() { - chErrors <- cli.hijack("POST", "/containers/"+out.Id+"/attach?logs=1&stream=1&stderr=1", config.Tty, nil, os.Stderr) + chErrors <- cli.hijack("POST", "/containers/"+out.ID+"/attach?logs=1&stream=1&stderr=1", config.Tty, nil, os.Stderr) }() } @@ -1262,7 +1266,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { v.Set("stderr", "1") } go func() { - chErrors <- cli.hijack("POST", "/containers/"+out.Id+"/attach?"+v.Encode(), config.Tty, os.Stdin, os.Stdout) + chErrors <- cli.hijack("POST", "/containers/"+out.ID+"/attach?"+v.Encode(), config.Tty, os.Stdin, os.Stdout) }() for connections > 0 { err := <-chErrors @@ -1272,9 +1276,6 @@ func (cli *DockerCli) CmdRun(args ...string) error { connections -= 1 } } - if !config.AttachStdout && !config.AttachStderr { - fmt.Println(out.Id) - } return nil } @@ -1322,7 +1323,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int, params = bytes.NewBuffer(buf) } - req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, API_VERSION, path), params) + req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, APIVERSION, path), params) if err != nil { return nil, -1, err } @@ -1354,7 +1355,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e if (method == "POST" || method == "PUT") && in == nil { in = bytes.NewReader([]byte{}) } - req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, API_VERSION, path), in) + req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.host, cli.port, APIVERSION, path), in) if err != nil { return err } @@ -1381,14 +1382,14 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e if resp.Header.Get("Content-Type") == "application/json" { dec := json.NewDecoder(resp.Body) for { - var m utils.JsonMessage + var m utils.JSONMessage if err := dec.Decode(&m); err == io.EOF { break } else if err != nil { return err } if m.Progress != "" { - fmt.Fprintf(out, "Downloading %s\r", m.Progress) + fmt.Fprintf(out, "%s %s\r", m.Status, m.Progress) } else if m.Error != "" { return fmt.Errorf(m.Error) } else { @@ -1404,7 +1405,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e } func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.File, out io.Writer) error { - req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", API_VERSION, path), nil) + req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", APIVERSION, path), nil) if err != nil { return err } @@ -1425,12 +1426,12 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi return err }) - if in != nil && setRawTerminal && term.IsTerminal(int(in.Fd())) && os.Getenv("NORAW") == "" { - if oldState, err := term.SetRawTerminal(); err != nil { + if in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" { + oldState, err := term.SetRawTerminal() + if err != nil { return err - } else { - defer term.RestoreTerminal(oldState) } + defer term.RestoreTerminal(oldState) } sendStdin := utils.Go(func() error { _, err := io.Copy(rwc, in) @@ -1444,7 +1445,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi return err } - if !term.IsTerminal(int(os.Stdin.Fd())) { + if !term.IsTerminal(os.Stdin.Fd()) { if err := <-sendStdin; err != nil { return err } diff --git a/components/engine/container.go b/components/engine/container.go index c6b7c8a51c..29c07eea0b 100644 --- a/components/engine/container.go +++ b/components/engine/container.go @@ -23,7 +23,7 @@ import ( type Container struct { root string - Id string + ID string Created time.Time @@ -167,8 +167,8 @@ func ParseRun(args []string, capabilities *Capabilities) (*Config, *flag.FlagSet } type NetworkSettings struct { - IpAddress string - IpPrefixLen int + IPAddress string + IPPrefixLen int Gateway string Bridge string PortMapping map[string]string @@ -409,7 +409,7 @@ func (container *Container) Start() error { defer container.State.unlock() if container.State.Running { - return fmt.Errorf("The container %s is already running.", container.Id) + return fmt.Errorf("The container %s is already running.", container.ID) } if err := container.EnsureMounted(); err != nil { return err @@ -431,24 +431,24 @@ func (container *Container) Start() error { // Create the requested volumes volumes for volPath := range container.Config.Volumes { - if c, err := container.runtime.volumes.Create(nil, container, "", "", nil); err != nil { + c, err := container.runtime.volumes.Create(nil, container, "", "", nil) + if err != nil { return err - } else { - if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { - return nil - } - container.Volumes[volPath] = c.Id } + if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { + return nil + } + container.Volumes[volPath] = c.ID } if container.Config.VolumesFrom != "" { c := container.runtime.Get(container.Config.VolumesFrom) if c == nil { - return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.Id) + return fmt.Errorf("Container %s not found. Impossible to mount its volumes", container.ID) } for volPath, id := range c.Volumes { if _, exists := container.Volumes[volPath]; exists { - return fmt.Errorf("The requested volume %s overlap one of the volume of the container %s", volPath, c.Id) + return fmt.Errorf("The requested volume %s overlap one of the volume of the container %s", volPath, c.ID) } if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { return nil @@ -462,7 +462,7 @@ func (container *Container) Start() error { } params := []string{ - "-n", container.Id, + "-n", container.ID, "-f", container.lxcConfigPath(), "--", "/sbin/init", @@ -573,17 +573,17 @@ func (container *Container) allocateNetwork() error { } container.NetworkSettings.PortMapping = make(map[string]string) for _, spec := range container.Config.PortSpecs { - if nat, err := iface.AllocatePort(spec); err != nil { + nat, err := iface.AllocatePort(spec) + if err != nil { iface.Release() return err - } else { - container.NetworkSettings.PortMapping[strconv.Itoa(nat.Backend)] = strconv.Itoa(nat.Frontend) } + container.NetworkSettings.PortMapping[strconv.Itoa(nat.Backend)] = strconv.Itoa(nat.Frontend) } container.network = iface container.NetworkSettings.Bridge = container.runtime.networkManager.bridgeIface - container.NetworkSettings.IpAddress = iface.IPNet.IP.String() - container.NetworkSettings.IpPrefixLen, _ = iface.IPNet.Mask.Size() + container.NetworkSettings.IPAddress = iface.IPNet.IP.String() + container.NetworkSettings.IPPrefixLen, _ = iface.IPNet.Mask.Size() container.NetworkSettings.Gateway = iface.Gateway.String() return nil } @@ -597,16 +597,16 @@ func (container *Container) releaseNetwork() { // FIXME: replace this with a control socket within docker-init func (container *Container) waitLxc() error { for { - if output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput(); err != nil { + output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput() + if err != nil { return err - } else { - if !strings.Contains(string(output), "RUNNING") { - return nil - } + } + if !strings.Contains(string(output), "RUNNING") { + return nil } time.Sleep(500 * time.Millisecond) } - return nil + panic("Unreachable") } func (container *Container) monitor() { @@ -616,17 +616,17 @@ func (container *Container) monitor() { // If the command does not exists, try to wait via lxc if container.cmd == nil { if err := container.waitLxc(); err != nil { - utils.Debugf("%s: Process: %s", container.Id, err) + utils.Debugf("%s: Process: %s", container.ID, err) } } else { if err := container.cmd.Wait(); err != nil { // Discard the error as any signals or non 0 returns will generate an error - utils.Debugf("%s: Process: %s", container.Id, err) + utils.Debugf("%s: Process: %s", container.ID, err) } } utils.Debugf("Process finished") - var exitCode int = -1 + exitCode := -1 if container.cmd != nil { exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() } @@ -635,24 +635,24 @@ func (container *Container) monitor() { container.releaseNetwork() if container.Config.OpenStdin { if err := container.stdin.Close(); err != nil { - utils.Debugf("%s: Error close stdin: %s", container.Id, err) + utils.Debugf("%s: Error close stdin: %s", container.ID, err) } } if err := container.stdout.CloseWriters(); err != nil { - utils.Debugf("%s: Error close stdout: %s", container.Id, err) + utils.Debugf("%s: Error close stdout: %s", container.ID, err) } if err := container.stderr.CloseWriters(); err != nil { - utils.Debugf("%s: Error close stderr: %s", container.Id, err) + utils.Debugf("%s: Error close stderr: %s", container.ID, err) } if container.ptyMaster != nil { if err := container.ptyMaster.Close(); err != nil { - utils.Debugf("%s: Error closing Pty master: %s", container.Id, err) + utils.Debugf("%s: Error closing Pty master: %s", container.ID, err) } } if err := container.Unmount(); err != nil { - log.Printf("%v: Failed to umount filesystem: %v", container.Id, err) + log.Printf("%v: Failed to umount filesystem: %v", container.ID, err) } // Re-create a brand new stdin pipe once the container exited @@ -673,7 +673,7 @@ func (container *Container) monitor() { // This is because State.setStopped() has already been called, and has caused Wait() // to return. // FIXME: why are we serializing running state to disk in the first place? - //log.Printf("%s: Failed to dump configuration to the disk: %s", container.Id, err) + //log.Printf("%s: Failed to dump configuration to the disk: %s", container.ID, err) } } @@ -683,17 +683,17 @@ func (container *Container) kill() error { } // Sending SIGKILL to the process via lxc - output, err := exec.Command("lxc-kill", "-n", container.Id, "9").CombinedOutput() + output, err := exec.Command("lxc-kill", "-n", container.ID, "9").CombinedOutput() if err != nil { - log.Printf("error killing container %s (%s, %s)", container.Id, output, err) + log.Printf("error killing container %s (%s, %s)", container.ID, output, err) } // 2. Wait for the process to die, in last resort, try to kill the process directly if err := container.WaitTimeout(10 * time.Second); err != nil { if container.cmd == nil { - return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.Id) + return fmt.Errorf("lxc-kill failed, impossible to kill the container %s", container.ID) } - log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.Id) + log.Printf("Container %s failed to exit within 10 seconds of lxc SIGKILL - trying direct SIGKILL", container.ID) if err := container.cmd.Process.Kill(); err != nil { return err } @@ -721,7 +721,7 @@ func (container *Container) Stop(seconds int) error { } // 1. Send a SIGTERM - if output, err := exec.Command("lxc-kill", "-n", container.Id, "15").CombinedOutput(); err != nil { + if output, err := exec.Command("lxc-kill", "-n", container.ID, "15").CombinedOutput(); err != nil { log.Print(string(output)) log.Print("Failed to send SIGTERM to the process, force killing") if err := container.kill(); err != nil { @@ -731,7 +731,7 @@ func (container *Container) Stop(seconds int) error { // 2. Wait for the process to exit on its own if err := container.WaitTimeout(time.Duration(seconds) * time.Second); err != nil { - log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.Id, seconds) + log.Printf("Container %v failed to exit within %d seconds of SIGTERM - using the force", container.ID, seconds) if err := container.kill(); err != nil { return err } @@ -795,7 +795,8 @@ func (container *Container) WaitTimeout(timeout time.Duration) error { case <-done: return nil } - panic("unreachable") + + panic("Unreachable") } func (container *Container) EnsureMounted() error { @@ -838,16 +839,16 @@ func (container *Container) Unmount() error { return Unmount(container.RootfsPath()) } -// ShortId returns a shorthand version of the container's id for convenience. +// ShortID returns a shorthand version of the container's id for convenience. // A collision with other container shorthands is very unlikely, but possible. // In case of a collision a lookup with Runtime.Get() will fail, and the caller // will need to use a langer prefix, or the full-length container Id. -func (container *Container) ShortId() string { - return utils.TruncateId(container.Id) +func (container *Container) ShortID() string { + return utils.TruncateID(container.ID) } func (container *Container) logPath(name string) string { - return path.Join(container.root, fmt.Sprintf("%s-%s.log", container.Id, name)) + return path.Join(container.root, fmt.Sprintf("%s-%s.log", container.ID, name)) } func (container *Container) ReadLog(name string) (io.Reader, error) { @@ -887,7 +888,7 @@ func (container *Container) rwPath() string { return path.Join(container.root, "rw") } -func validateId(id string) error { +func validateID(id string) error { if id == "" { return fmt.Errorf("Invalid empty id") } diff --git a/components/engine/container_test.go b/components/engine/container_test.go index 3ed1763a3e..8ec1fa40ee 100644 --- a/components/engine/container_test.go +++ b/components/engine/container_test.go @@ -14,7 +14,7 @@ import ( "time" ) -func TestIdFormat(t *testing.T) { +func TestIDFormat(t *testing.T) { runtime, err := newTestRuntime() if err != nil { t.Fatal(err) @@ -22,19 +22,19 @@ func TestIdFormat(t *testing.T) { defer nuke(runtime) container1, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sh", "-c", "echo hello world"}, }, ) if err != nil { t.Fatal(err) } - match, err := regexp.Match("^[0-9a-f]{64}$", []byte(container1.Id)) + match, err := regexp.Match("^[0-9a-f]{64}$", []byte(container1.ID)) if err != nil { t.Fatal(err) } if !match { - t.Fatalf("Invalid container ID: %s", container1.Id) + t.Fatalf("Invalid container ID: %s", container1.ID) } } @@ -46,7 +46,7 @@ func TestMultipleAttachRestart(t *testing.T) { defer nuke(runtime) container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sh", "-c", "i=1; while [ $i -le 5 ]; do i=`expr $i + 1`; echo hello; done"}, }, @@ -153,7 +153,7 @@ func TestDiff(t *testing.T) { // Create a container and remove a file container1, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/rm", "/etc/passwd"}, }, ) @@ -194,7 +194,7 @@ func TestDiff(t *testing.T) { // Create a new container from the commited image container2, err := builder.Create( &Config{ - Image: img.Id, + Image: img.ID, Cmd: []string{"cat", "/etc/passwd"}, }, ) @@ -217,6 +217,37 @@ func TestDiff(t *testing.T) { t.Fatalf("/etc/passwd should not be present in the diff after commit.") } } + + // Create a new containere + container3, err := builder.Create( + &Config{ + Image: GetTestImage(runtime).ID, + Cmd: []string{"rm", "/bin/httpd"}, + }, + ) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container3) + + if err := container3.Run(); err != nil { + t.Fatal(err) + } + + // Check the changelog + c, err = container3.Changes() + if err != nil { + t.Fatal(err) + } + success = false + for _, elem := range c { + if elem.Path == "/bin/httpd" && elem.Kind == 2 { + success = true + } + } + if !success { + t.Fatalf("/bin/httpd should be present in the diff after commit.") + } } func TestCommitAutoRun(t *testing.T) { @@ -229,7 +260,7 @@ func TestCommitAutoRun(t *testing.T) { builder := NewBuilder(runtime) container1, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sh", "-c", "echo hello > /world"}, }, ) @@ -260,7 +291,7 @@ func TestCommitAutoRun(t *testing.T) { // FIXME: Make a TestCommit that stops here and check docker.root/layers/img.id/world container2, err := builder.Create( &Config{ - Image: img.Id, + Image: img.ID, }, ) if err != nil { @@ -309,7 +340,7 @@ func TestCommitRun(t *testing.T) { container1, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/sh", "-c", "echo hello > /world"}, }, ) @@ -341,7 +372,7 @@ func TestCommitRun(t *testing.T) { container2, err := builder.Create( &Config{ - Image: img.Id, + Image: img.ID, Cmd: []string{"cat", "/world"}, }, ) @@ -388,7 +419,7 @@ func TestStart(t *testing.T) { defer nuke(runtime) container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Memory: 33554432, CpuShares: 1000, Cmd: []string{"/bin/cat"}, @@ -432,7 +463,7 @@ func TestRun(t *testing.T) { defer nuke(runtime) container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -460,7 +491,7 @@ func TestOutput(t *testing.T) { defer nuke(runtime) container, err := NewBuilder(runtime).Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foobar"}, }, ) @@ -484,7 +515,7 @@ func TestKillDifferentUser(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"tail", "-f", "/etc/resolv.conf"}, User: "daemon", }, @@ -532,7 +563,7 @@ func TestKill(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat", "/dev/zero"}, }, ) @@ -580,7 +611,7 @@ func TestExitCode(t *testing.T) { builder := NewBuilder(runtime) trueContainer, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/true", ""}, }) if err != nil { @@ -595,7 +626,7 @@ func TestExitCode(t *testing.T) { } falseContainer, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/false", ""}, }) if err != nil { @@ -617,7 +648,7 @@ func TestRestart(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foobar"}, }, ) @@ -650,7 +681,7 @@ func TestRestartStdin(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat"}, OpenStdin: true, @@ -732,7 +763,7 @@ func TestUser(t *testing.T) { // Default user must be root container, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, }, ) @@ -750,7 +781,7 @@ func TestUser(t *testing.T) { // Set a username container, err = builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, User: "root", @@ -770,7 +801,7 @@ func TestUser(t *testing.T) { // Set a UID container, err = builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, User: "0", @@ -790,7 +821,7 @@ func TestUser(t *testing.T) { // Set a different user by uid container, err = builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, User: "1", @@ -812,7 +843,7 @@ func TestUser(t *testing.T) { // Set a different user by username container, err = builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"id"}, User: "daemon", @@ -841,7 +872,7 @@ func TestMultipleContainers(t *testing.T) { builder := NewBuilder(runtime) container1, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat", "/dev/zero"}, }, ) @@ -851,7 +882,7 @@ func TestMultipleContainers(t *testing.T) { defer runtime.Destroy(container1) container2, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat", "/dev/zero"}, }, ) @@ -897,7 +928,7 @@ func TestStdin(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat"}, OpenStdin: true, @@ -944,7 +975,7 @@ func TestTty(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"cat"}, OpenStdin: true, @@ -991,7 +1022,7 @@ func TestEnv(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/usr/bin/env"}, }, ) @@ -1069,7 +1100,7 @@ func TestLXCConfig(t *testing.T) { cpuMax := 10000 cpu := cpuMin + rand.Intn(cpuMax-cpuMin) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"/bin/true"}, Hostname: "foobar", @@ -1097,7 +1128,7 @@ func BenchmarkRunSequencial(b *testing.B) { defer nuke(runtime) for i := 0; i < b.N; i++ { container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foo"}, }, ) @@ -1132,7 +1163,7 @@ func BenchmarkRunParallel(b *testing.B) { tasks = append(tasks, complete) go func(i int, complete chan error) { container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"echo", "-n", "foo"}, }, ) diff --git a/components/engine/contrib/crashTest.go b/components/engine/contrib/crashTest.go index d4a889e8d3..b3dbacaf03 100644 --- a/components/engine/contrib/crashTest.go +++ b/components/engine/contrib/crashTest.go @@ -11,13 +11,13 @@ import ( "time" ) -var DOCKER_PATH string = path.Join(os.Getenv("DOCKERPATH"), "docker") +var DOCKERPATH = path.Join(os.Getenv("DOCKERPATH"), "docker") // WARNING: this crashTest will 1) crash your host, 2) remove all containers func runDaemon() (*exec.Cmd, error) { os.Remove("/var/run/docker.pid") exec.Command("rm", "-rf", "/var/lib/docker/containers").Run() - cmd := exec.Command(DOCKER_PATH, "-d") + cmd := exec.Command(DOCKERPATH, "-d") outPipe, err := cmd.StdoutPipe() if err != nil { return nil, err @@ -77,7 +77,7 @@ func crashTest() error { stop = false for i := 0; i < 100 && !stop; { func() error { - cmd := exec.Command(DOCKER_PATH, "run", "base", "echo", fmt.Sprintf("%d", totalTestCount)) + cmd := exec.Command(DOCKERPATH, "run", "base", "echo", fmt.Sprintf("%d", totalTestCount)) i++ totalTestCount++ outPipe, err := cmd.StdoutPipe() diff --git a/components/engine/contrib/docker-build/MAINTAINERS b/components/engine/contrib/docker-build/MAINTAINERS deleted file mode 100644 index e1c6f2ccfc..0000000000 --- a/components/engine/contrib/docker-build/MAINTAINERS +++ /dev/null @@ -1 +0,0 @@ -Solomon Hykes diff --git a/components/engine/contrib/docker-build/README b/components/engine/contrib/docker-build/README deleted file mode 100644 index f648753b90..0000000000 --- a/components/engine/contrib/docker-build/README +++ /dev/null @@ -1,68 +0,0 @@ -# docker-build: build your software with docker - -## Description - -docker-build is a script to build docker images from source. It will be deprecated once the 'build' feature is incorporated into docker itself (See https://github.com/dotcloud/docker/issues/278) - -Author: Solomon Hykes - - -## Install - -docker-builder requires: - -1) A reasonably recent Python setup (tested on 2.7.2). - -2) A running docker daemon at version 0.1.4 or more recent (http://www.docker.io/gettingstarted) - - -## Usage - -First create a valid Changefile, which defines a sequence of changes to apply to a base image. - - $ cat Changefile - # Start build from a know base image - from base:ubuntu-12.10 - # Update ubuntu sources - run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list - run apt-get update - # Install system packages - run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git - run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl - run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang - # Insert files from the host (./myscript must be present in the current directory) - copy myscript /usr/local/bin/myscript - - -Run docker-build, and pass the contents of your Changefile as standard input. - - $ IMG=$(./docker-build < Changefile) - -This will take a while: for each line of the changefile, docker-build will: - -1. Create a new container to execute the given command or insert the given file -2. Wait for the container to complete execution -3. Commit the resulting changes as a new image -4. Use the resulting image as the input of the next step - - -If all the steps succeed, the result will be an image containing the combined results of each build step. -You can trace back those build steps by inspecting the image's history: - - $ docker history $IMG - ID CREATED CREATED BY - 1e9e2045de86 A few seconds ago /bin/sh -c cat > /usr/local/bin/myscript; chmod +x /usr/local/bin/git - 77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang - 77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl - 77db140aa62a A few seconds ago /bin/sh -c DEBIAN_FRONTEND=noninteractive apt-get install -y -q git - 83e85d155451 A few seconds ago /bin/sh -c apt-get update - bfd53b36d9d3 A few seconds ago /bin/sh -c echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list - base 2 weeks ago /bin/bash - 27cf78414709 2 weeks ago - - -Note that your build started from 'base', as instructed by your Changefile. But that base image itself seems to have been built in 2 steps - hence the extra step in the history. - - -You can use this build technique to create any image you want: a database, a web application, or anything else that can be build by a sequence of unix commands - in other words, anything else. - diff --git a/components/engine/contrib/docker-build/docker-build b/components/engine/contrib/docker-build/docker-build deleted file mode 100755 index 654cc89793..0000000000 --- a/components/engine/contrib/docker-build/docker-build +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python - -# docker-build is a script to build docker images from source. -# It will be deprecated once the 'build' feature is incorporated into docker itself. -# (See https://github.com/dotcloud/docker/issues/278) -# -# Author: Solomon Hykes - - - -# First create a valid Changefile, which defines a sequence of changes to apply to a base image. -# -# $ cat Changefile -# # Start build from a know base image -# from base:ubuntu-12.10 -# # Update ubuntu sources -# run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list -# run apt-get update -# # Install system packages -# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git -# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl -# run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang -# # Insert files from the host (./myscript must be present in the current directory) -# copy myscript /usr/local/bin/myscript -# -# -# Run docker-build, and pass the contents of your Changefile as standard input. -# -# $ IMG=$(./docker-build < Changefile) -# -# This will take a while: for each line of the changefile, docker-build will: -# -# 1. Create a new container to execute the given command or insert the given file -# 2. Wait for the container to complete execution -# 3. Commit the resulting changes as a new image -# 4. Use the resulting image as the input of the next step - - -import sys -import subprocess -import json -import hashlib - -def docker(args, stdin=None): - print "# docker " + " ".join(args) - p = subprocess.Popen(["docker"] + list(args), stdin=stdin, stdout=subprocess.PIPE) - return p.stdout - -def image_exists(img): - return docker(["inspect", img]).read().strip() != "" - -def image_config(img): - return json.loads(docker(["inspect", img]).read()).get("config", {}) - -def run_and_commit(img_in, cmd, stdin=None, author=None, run=None): - run_id = docker(["run"] + (["-i", "-a", "stdin"] if stdin else ["-d"]) + [img_in, "/bin/sh", "-c", cmd], stdin=stdin).read().rstrip() - print "---> Waiting for " + run_id - result=int(docker(["wait", run_id]).read().rstrip()) - if result != 0: - print "!!! '{}' return non-zero exit code '{}'. Aborting.".format(cmd, result) - sys.exit(1) - return docker(["commit"] + (["-author", author] if author else []) + (["-run", json.dumps(run)] if run is not None else []) + [run_id]).read().rstrip() - -def insert(base, src, dst, author=None): - print "COPY {} to {} in {}".format(src, dst, base) - if dst == "": - raise Exception("Missing destination path") - stdin = file(src) - stdin.seek(0) - return run_and_commit(base, "cat > {0}; chmod +x {0}".format(dst), stdin=stdin, author=author) - -def add(base, src, dst, author=None): - print "PUSH to {} in {}".format(dst, base) - if src == ".": - tar = subprocess.Popen(["tar", "-c", "."], stdout=subprocess.PIPE).stdout - else: - tar = subprocess.Popen(["curl", src], stdout=subprocess.PIPE).stdout - if dst == "": - raise Exception("Missing argument to push") - return run_and_commit(base, "mkdir -p '{0}' && tar -C '{0}' -x".format(dst), stdin=tar, author=author) - -def main(): - base="" - maintainer="" - steps = [] - try: - for line in sys.stdin.readlines(): - line = line.strip() - # Skip comments and empty lines - if line == "" or line[0] == "#": - continue - op, param = line.split(None, 1) - print op.upper() + " " + param - if op == "from": - base = param - steps.append(base) - elif op == "maintainer": - maintainer = param - elif op == "run": - result = run_and_commit(base, param, author=maintainer) - steps.append(result) - base = result - print "===> " + base - elif op == "copy": - src, dst = param.split(" ", 1) - result = insert(base, src, dst, author=maintainer) - steps.append(result) - base = result - print "===> " + base - elif op == "add": - src, dst = param.split(" ", 1) - result = add(base, src, dst, author=maintainer) - steps.append(result) - base=result - print "===> " + base - elif op == "expose": - config = image_config(base) - if config.get("PortSpecs") is None: - config["PortSpecs"] = [] - portspec = param.strip() - config["PortSpecs"].append(portspec) - result = run_and_commit(base, "# (nop) expose port {}".format(portspec), author=maintainer, run=config) - steps.append(result) - base=result - print "===> " + base - elif op == "cmd": - config = image_config(base) - cmd = list(json.loads(param)) - config["Cmd"] = cmd - result = run_and_commit(base, "# (nop) set default command to '{}'".format(" ".join(cmd)), author=maintainer, run=config) - steps.append(result) - base=result - print "===> " + base - else: - print "Skipping uknown op " + op - except: - docker(["rmi"] + steps[1:]) - raise - print base - -if __name__ == "__main__": - main() diff --git a/components/engine/contrib/docker-build/example.changefile b/components/engine/contrib/docker-build/example.changefile deleted file mode 100644 index d76bbb4389..0000000000 --- a/components/engine/contrib/docker-build/example.changefile +++ /dev/null @@ -1,13 +0,0 @@ -# Start build from a know base image -maintainer Solomon Hykes -from base:ubuntu-12.10 -# Update ubuntu sources -run echo 'deb http://archive.ubuntu.com/ubuntu quantal main universe multiverse' > /etc/apt/sources.list -run apt-get update -# Install system packages -run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git -run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl -run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang -# Insert files from the host (./myscript must be present in the current directory) -copy myscript /usr/local/bin/myscript -push /src diff --git a/components/engine/contrib/docker-build/myscript b/components/engine/contrib/docker-build/myscript deleted file mode 100644 index a6ffda5f11..0000000000 --- a/components/engine/contrib/docker-build/myscript +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo hello, world! diff --git a/components/engine/docker/docker.go b/components/engine/docker/docker.go index 7b8aa7f858..dada16e11e 100644 --- a/components/engine/docker/docker.go +++ b/components/engine/docker/docker.go @@ -15,7 +15,7 @@ import ( ) var ( - GIT_COMMIT string + GITCOMMIT string ) func main() { @@ -59,7 +59,7 @@ func main() { if *flDebug { os.Setenv("DEBUG", "1") } - docker.GIT_COMMIT = GIT_COMMIT + docker.GITCOMMIT = GITCOMMIT if *flDaemon { if flag.NArg() != 0 { flag.Usage() diff --git a/components/engine/docs/Makefile b/components/engine/docs/Makefile index dcbf111c29..517d01658f 100644 --- a/components/engine/docs/Makefile +++ b/components/engine/docs/Makefile @@ -63,7 +63,7 @@ site: connect: @echo connecting dotcloud to www.docker.io website, make sure to use user 1 @cd _build/website/ ; \ - dotcloud connect dockerwebsite ; + dotcloud connect dockerwebsite ; \ dotcloud list push: diff --git a/components/engine/docs/sources/api/docker_remote_api.rst b/components/engine/docs/sources/api/docker_remote_api.rst index e27aab13bd..c1fbae4631 100644 --- a/components/engine/docs/sources/api/docker_remote_api.rst +++ b/components/engine/docs/sources/api/docker_remote_api.rst @@ -564,7 +564,7 @@ Create an image Content-Type: application/json {"status":"Pulling..."} - {"progress":"1/? (n/a)"} + {"status":"Pulling", "progress":"1/? (n/a)"} {"error":"Invalid..."} ... @@ -607,7 +607,7 @@ Insert a file in a image Content-Type: application/json {"status":"Inserting..."} - {"progress":"1/? (n/a)"} + {"status":"Inserting", "progress":"1/? (n/a)"} {"error":"Invalid..."} ... @@ -734,7 +734,7 @@ Push an image on the registry Content-Type: application/json {"status":"Pushing..."} - {"progress":"1/? (n/a)"} + {"status":"Pushing", "progress":"1/? (n/a)"} {"error":"Invalid..."} ... @@ -974,10 +974,12 @@ Display system-wide information { "Containers":11, - "Version":"0.2.2", "Images":16, - "GoVersion":"go1.0.3", - "Debug":false + "Debug":false, + "NFd": 11, + "NGoroutines":21, + "MemoryLimit":true, + "SwapLimit":false } :statuscode 200: no error @@ -1003,12 +1005,11 @@ Show the docker version information HTTP/1.1 200 OK Content-Type: application/json - + { "Version":"0.2.2", "GitCommit":"5a2a5cc+CHANGES", - "MemoryLimit":true, - "SwapLimit":false + "GoVersion":"go1.0.3" } :statuscode 200: no error diff --git a/components/engine/docs/sources/contributing/contributing.rst b/components/engine/docs/sources/contributing/contributing.rst index 25b4df763a..1913cec30d 100644 --- a/components/engine/docs/sources/contributing/contributing.rst +++ b/components/engine/docs/sources/contributing/contributing.rst @@ -5,5 +5,5 @@ Contributing to Docker ====================== -Want to hack on Docker? Awesome! The repository includes `all the instructions you need to get started `. +Want to hack on Docker? Awesome! The repository includes `all the instructions you need to get started `_. diff --git a/components/engine/docs/sources/contributing/devenvironment.rst b/components/engine/docs/sources/contributing/devenvironment.rst index b5742c780a..5d937c5a44 100644 --- a/components/engine/docs/sources/contributing/devenvironment.rst +++ b/components/engine/docs/sources/contributing/devenvironment.rst @@ -5,11 +5,35 @@ Setting Up a Dev Environment ============================ -Instructions that have been verified to work on Ubuntu 12.10, +Instructions that have been verified to work on Ubuntu Precise 12.04 (LTS) (64-bit), + + +Dependencies +------------ + +**Linux kernel 3.8** + +Due to a bug in LXC docker works best on the 3.8 kernel. Precise comes with a 3.2 kernel, so we need to upgrade it. The kernel we install comes with AUFS built in. + .. code-block:: bash - sudo apt-get -y install lxc wget bsdtar curl golang git + # install the backported kernel + sudo apt-get update && sudo apt-get install linux-image-generic-lts-raring + + # reboot + sudo reboot + + +Installation +------------ + +.. code-block:: bash + + sudo apt-get install python-software-properties + sudo add-apt-repository ppa:gophers/go + sudo apt-get update + sudo apt-get -y install lxc wget bsdtar curl golang-stable git export GOPATH=~/go/ export PATH=$GOPATH/bin:$PATH diff --git a/components/engine/docs/sources/faq.rst b/components/engine/docs/sources/faq.rst index 901e51ddbb..12b9751338 100644 --- a/components/engine/docs/sources/faq.rst +++ b/components/engine/docs/sources/faq.rst @@ -19,7 +19,8 @@ Most frequently asked questions. 3. **Does Docker run on Mac OS X or Windows?** - Not at this time, Docker currently only runs on Linux, but you can use VirtualBox to run Docker in a virtual machine on your box, and get the best of both worlds. Check out the MacOSX_ and Windows_ installation guides. + Not at this time, Docker currently only runs on Linux, but you can use VirtualBox to run Docker in a + virtual machine on your box, and get the best of both worlds. Check out the :ref:`install_using_vagrant` and :ref:`windows` installation guides. 4. **How do containers compare to virtual machines?** @@ -34,15 +35,16 @@ Most frequently asked questions. You can find more answers on: - * `IRC: docker on freenode`_ + * `Docker club mailinglist`_ + * `IRC, docker on freenode`_ * `Github`_ * `Ask questions on Stackoverflow`_ * `Join the conversation on Twitter`_ - .. _Windows: ../installation/windows/ - .. _MacOSX: ../installation/vagrant/ + + .. _Docker club mailinglist: https://groups.google.com/d/forum/docker-club .. _the repo: http://www.github.com/dotcloud/docker - .. _IRC\: docker on freenode: irc://chat.freenode.net#docker + .. _IRC, docker on freenode: irc://chat.freenode.net#docker .. _Github: http://www.github.com/dotcloud/docker .. _Ask questions on Stackoverflow: http://stackoverflow.com/search?q=docker .. _Join the conversation on Twitter: http://twitter.com/getdocker diff --git a/components/engine/docs/sources/installation/ubuntulinux.rst b/components/engine/docs/sources/installation/ubuntulinux.rst index 1fb1ce5299..ed592d3a9d 100644 --- a/components/engine/docs/sources/installation/ubuntulinux.rst +++ b/components/engine/docs/sources/installation/ubuntulinux.rst @@ -92,6 +92,16 @@ have AUFS filesystem support enabled, so we need to install it. sudo apt-get update sudo apt-get install linux-image-extra-`uname -r` +**add-apt-repository support** + +Some installations of Ubuntu 13.04 require ``software-properties-common`` to be +installed before being able to use add-apt-repository. + +.. code-block:: bash + + sudo apt-get install software-properties-common + + Installation ------------ diff --git a/components/engine/docs/sources/installation/windows.rst b/components/engine/docs/sources/installation/windows.rst index 230ac78051..7830106020 100644 --- a/components/engine/docs/sources/installation/windows.rst +++ b/components/engine/docs/sources/installation/windows.rst @@ -2,6 +2,7 @@ :description: Docker's tutorial to run docker on Windows :keywords: Docker, Docker documentation, Windows, requirements, virtualbox, vagrant, git, ssh, putty, cygwin +.. _windows: Using Vagrant (Windows) ======================= diff --git a/components/engine/docs/sources/use/builder.rst b/components/engine/docs/sources/use/builder.rst index abd5b9ecb1..f2e9ce97ce 100644 --- a/components/engine/docs/sources/use/builder.rst +++ b/components/engine/docs/sources/use/builder.rst @@ -18,7 +18,7 @@ steps and commit them along the way, giving you a final image. To use Docker Builder, assemble the steps into a text file (commonly referred to as a Dockerfile) and supply this to `docker build` on STDIN, like so: - ``docker build < Dockerfile`` + ``docker build - < Dockerfile`` Docker will run your steps one-by-one, committing the result if necessary, before finally outputting the ID of your new image. diff --git a/components/engine/docs/theme/docker/layout.html b/components/engine/docs/theme/docker/layout.html index d212c9ca86..baaaec9155 100755 --- a/components/engine/docs/theme/docker/layout.html +++ b/components/engine/docs/theme/docker/layout.html @@ -64,14 +64,15 @@
@@ -86,8 +87,13 @@
-

DOCUMENTATION

+
+ +

DOCUMENTATION

+
@@ -123,8 +129,14 @@