From 2f89315bf882f6b507f843a65fcf08ba2ae91959 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Mon, 6 May 2013 17:00:21 -0600 Subject: [PATCH 01/79] Update mkimage-debian.sh now that wheezy is officially the stable release - also, we can't rely on "release" versions for testing or unstable - only "stable" has reliable release versions --- contrib/mkimage-debian.sh | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/contrib/mkimage-debian.sh b/contrib/mkimage-debian.sh index ace555ada6..89349e4acc 100755 --- a/contrib/mkimage-debian.sh +++ b/contrib/mkimage-debian.sh @@ -2,18 +2,15 @@ set -e # these should match the names found at http://www.debian.org/releases/ -stableSuite='squeeze' -testingSuite='wheezy' +stableSuite='wheezy' +testingSuite='jessie' unstableSuite='sid' -# if suite is equal to this, it gets the "latest" tag -latestSuite="$testingSuite" - variant='minbase' include='iproute,iputils-ping' repo="$1" -suite="${2:-$latestSuite}" +suite="${2:-$stableSuite}" mirror="${3:-}" # stick to the default debootstrap mirror if one is not provided if [ ! "$repo" ]; then @@ -41,17 +38,14 @@ img=$(sudo tar -c . | docker import -) # tag suite docker tag $img $repo $suite -if [ "$suite" = "$latestSuite" ]; then - # tag latest - docker tag $img $repo latest -fi - # test the image docker run -i -t $repo:$suite echo success -# unstable's version numbers match testing (since it's mostly just a sandbox for testing), so it doesn't get a version number tag -if [ "$suite" != "$unstableSuite" -a "$suite" != 'unstable' ]; then - # tag the specific version +if [ "$suite" = "$stableSuite" -o "$suite" = 'stable' ]; then + # tag latest + docker tag $img $repo latest + + # tag the specific debian release version ver=$(docker run $repo:$suite cat /etc/debian_version) docker tag $img $repo $ver fi From 2cf92abf0eff49b21812d88e74813b8848f9b758 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 24 May 2013 21:40:56 +0300 Subject: [PATCH 02/79] add arch field to image struct --- image.go | 1 + 1 file changed, 1 insertion(+) diff --git a/image.go b/image.go index 342c0c94b7..d825b4bba2 100644 --- a/image.go +++ b/image.go @@ -27,6 +27,7 @@ type Image struct { DockerVersion string `json:"docker_version,omitempty"` Author string `json:"author,omitempty"` Config *Config `json:"config,omitempty"` + Architecture string `json:"architecture,omitempty"` graph *Graph } From 5f69a53dba4b0e550ab29c7f2bf4277222927097 Mon Sep 17 00:00:00 2001 From: unclejack Date: Fri, 24 May 2013 21:42:09 +0300 Subject: [PATCH 03/79] set architecture to x86_64 by default We're going to hardcode architecture to amd64 for now. This is a stub and will have to be changed to set the actual arch. --- graph.go | 1 + 1 file changed, 1 insertion(+) diff --git a/graph.go b/graph.go index 5bf305fc22..6010c9b6ca 100644 --- a/graph.go +++ b/graph.go @@ -107,6 +107,7 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut DockerVersion: VERSION, Author: author, Config: config, + Architecture: "x86_64", } if container != nil { img.Parent = container.Image From cb0bc4adc297baeea8e7b74269765c35457e04e7 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sat, 25 May 2013 14:12:02 +0000 Subject: [PATCH 04/79] add error handling --- api.go | 3 ++- commands.go | 3 +++ utils/utils.go | 7 +++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 3164a886f6..e5816b255f 100644 --- a/api.go +++ b/api.go @@ -295,7 +295,8 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht w.Header().Set("Content-Type", "application/json") } if err := srv.ImagePull(image, tag, registry, w, version > 1.0); err != nil { - return err + fmt.Fprintf(w, utils.FormatError(err.Error(), version > 1.0)) + return nil } } else { //import if err := srv.ImageImport(src, repo, tag, r.Body, w); err != nil { diff --git a/commands.go b/commands.go index 6c4dcd14d6..01ab8a334f 100644 --- a/commands.go +++ b/commands.go @@ -1261,6 +1261,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e type Message struct { Status string `json:"status,omitempty"` Progress string `json:"progress,omitempty"` + Error string `json:"error,omitempty"` } dec := json.NewDecoder(resp.Body) for { @@ -1272,6 +1273,8 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e } if m.Progress != "" { fmt.Fprintf(out, "Downloading %s\r", m.Progress) + } else if m.Error != "" { + return fmt.Errorf(m.Error) } else { fmt.Fprintf(out, "%s\n", m.Status) } diff --git a/utils/utils.go b/utils/utils.go index 233c624b68..8588c52478 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -564,6 +564,13 @@ func FormatStatus(str string, json bool) string { return str + "\r\n" } +func FormatError(str string, json bool) string { + if json { + return "{\"error\" : \"" + str + "\"}" + } + return "Error: " + str + "\r\n" +} + func FormatProgress(str string, json bool) string { if json { return "{\"progress\" : \"" + str + "\"}" From c8c7094b2e8088210e2182e582264e09222c6e3d Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sat, 25 May 2013 15:09:46 +0000 Subject: [PATCH 05/79] imporved error, push, import insert --- api.go | 44 ++++++++++++++++++++++-------- graph.go | 2 +- runtime_test.go | 2 +- server.go | 72 ++++++++++++++++++++++++------------------------- utils/utils.go | 44 ++++++++++++++++++++---------- 5 files changed, 101 insertions(+), 63 deletions(-) diff --git a/api.go b/api.go index e5816b255f..55fb8d5a66 100644 --- a/api.go +++ b/api.go @@ -289,17 +289,25 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht tag := r.Form.Get("tag") repo := r.Form.Get("repo") + if version > 1.0 { + w.Header().Set("Content-Type", "application/json") + } + sf := utils.NewStreamFormatter(version > 1.0) if image != "" { //pull registry := r.Form.Get("registry") - if version > 1.0 { - w.Header().Set("Content-Type", "application/json") - } - if err := srv.ImagePull(image, tag, registry, w, version > 1.0); err != nil { - fmt.Fprintf(w, utils.FormatError(err.Error(), version > 1.0)) - return nil + if err := srv.ImagePull(image, tag, registry, w, sf); err != nil { + if sf.Used() { + fmt.Fprintf(w, sf.FormatError(err)) + return nil + } + return err } } else { //import - if err := srv.ImageImport(src, repo, tag, r.Body, w); err != nil { + if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil { + if sf.Used() { + fmt.Fprintf(w, sf.FormatError(err)) + return nil + } return err } } @@ -335,8 +343,15 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht return fmt.Errorf("Missing parameter") } name := vars["name"] - - if err := srv.ImageInsert(name, url, path, w); err != nil { + if version > 1.0 { + w.Header().Set("Content-Type", "application/json") + } + sf := utils.NewStreamFormatter(version > 1.0) + if err := srv.ImageInsert(name, url, path, w, sf); err != nil { + if sf.Used() { + fmt.Fprintf(w, sf.FormatError(err)) + return nil + } return err } return nil @@ -352,8 +367,15 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http return fmt.Errorf("Missing parameter") } name := vars["name"] - - if err := srv.ImagePush(name, registry, w); err != nil { + if version > 1.0 { + w.Header().Set("Content-Type", "application/json") + } + sf := utils.NewStreamFormatter(version > 1.0) + if err := srv.ImagePush(name, registry, w, sf); err != nil { + if sf.Used() { + fmt.Fprintf(w, sf.FormatError(err)) + return nil + } return err } return nil diff --git a/graph.go b/graph.go index c0dd869227..0090d51636 100644 --- a/graph.go +++ b/graph.go @@ -165,7 +165,7 @@ func (graph *Graph) TempLayerArchive(id string, compression Compression, output if err != nil { return nil, err } - return NewTempArchive(utils.ProgressReader(ioutil.NopCloser(archive), 0, output, "Buffering to disk %v/%v (%v)", false), tmp.Root) + return NewTempArchive(utils.ProgressReader(ioutil.NopCloser(archive), 0, output, "Buffering to disk %v/%v (%v)", utils.NewStreamFormatter(false)), tmp.Root) } // Mktemp creates a temporary sub-directory inside the graph's filesystem. diff --git a/runtime_test.go b/runtime_test.go index 6c4ec5ded4..0dd71c48a3 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -75,7 +75,7 @@ func init() { registry: registry.NewRegistry(runtime.root), } // Retrieve the Image - if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, false); err != nil { + if err := srv.ImagePull(unitTestImageName, "", "", os.Stdout, utils.NewStreamFormatter(false)); err != nil { panic(err) } } diff --git a/server.go b/server.go index 3303c7c5a1..3353796475 100644 --- a/server.go +++ b/server.go @@ -67,7 +67,7 @@ func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) { return outs, nil } -func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error { +func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) img, err := srv.runtime.repositories.LookupImage(name) if err != nil { @@ -91,7 +91,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error { return err } - if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, "Downloading %v/%v (%v)\r", false), path); err != nil { + if err := c.Inject(utils.ProgressReader(file.Body, int(file.ContentLength), out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), path); err != nil { return err } // FIXME: Handle custom repo, tag comment, author @@ -99,7 +99,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error { if err != nil { return err } - fmt.Fprintf(out, "%s\n", img.Id) + fmt.Fprintf(out, sf.FormatStatus("%s"), img.Id) return nil } @@ -291,7 +291,7 @@ func (srv *Server) ContainerTag(name, repo, tag string, force bool) error { return nil } -func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []string, json bool) error { +func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []string, sf *utils.StreamFormatter) error { history, err := srv.registry.GetRemoteHistory(imgId, registry, token) if err != nil { return err @@ -301,7 +301,7 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri // FIXME: Launch the getRemoteImage() in goroutines for _, id := range history { if !srv.runtime.graph.Exists(id) { - fmt.Fprintf(out, utils.FormatStatus("Pulling %s metadata", json), id) + fmt.Fprintf(out, sf.FormatStatus("Pulling %s metadata"), id) imgJson, err := srv.registry.GetRemoteImageJson(id, registry, token) if err != nil { // FIXME: Keep goging in case of error? @@ -313,12 +313,12 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri } // Get the layer - fmt.Fprintf(out, utils.FormatStatus("Pulling %s fs layer", json), id) + fmt.Fprintf(out, sf.FormatStatus("Pulling %s fs layer"), id) layer, contentLength, err := srv.registry.GetRemoteImageLayer(img.Id, registry, token) if err != nil { return err } - if err := srv.runtime.graph.Register(utils.ProgressReader(layer, contentLength, out, utils.FormatProgress("%v/%v (%v)", json), json), false, img); err != nil { + if err := srv.runtime.graph.Register(utils.ProgressReader(layer, contentLength, out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), false, img); err != nil { return err } } @@ -326,8 +326,8 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri return nil } -func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, json bool) error { - fmt.Fprintf(out, utils.FormatStatus("Pulling repository %s from %s", json), remote, auth.IndexServerAddress()) +func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, sf *utils.StreamFormatter) error { + fmt.Fprintf(out, sf.FormatStatus("Pulling repository %s from %s"), remote, auth.IndexServerAddress()) repoData, err := srv.registry.GetRepositoryData(remote) if err != nil { return err @@ -364,11 +364,11 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, json b utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.Id) continue } - fmt.Fprintf(out, utils.FormatStatus("Pulling image %s (%s) from %s", json), img.Id, img.Tag, remote) + fmt.Fprintf(out, sf.FormatStatus("Pulling image %s (%s) from %s"), img.Id, img.Tag, remote) success := false for _, ep := range repoData.Endpoints { - if err := srv.pullImage(out, img.Id, "https://"+ep+"/v1", repoData.Tokens, json); err != nil { - fmt.Fprintf(out, utils.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint\n", json), askedTag, err) + if err := srv.pullImage(out, img.Id, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil { + fmt.Fprintf(out, sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint\n"), askedTag, err) continue } success = true @@ -393,16 +393,16 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, json b return nil } -func (srv *Server) ImagePull(name, tag, registry string, out io.Writer, json bool) error { +func (srv *Server) ImagePull(name, tag, registry string, out io.Writer, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) if registry != "" { - if err := srv.pullImage(out, name, registry, nil, json); err != nil { + if err := srv.pullImage(out, name, registry, nil, sf); err != nil { return err } return nil } - if err := srv.pullRepository(out, name, tag, json); err != nil { + if err := srv.pullRepository(out, name, tag, sf); err != nil { return err } @@ -475,14 +475,14 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]*registry.ImgDat return imgList, nil } -func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[string]string) error { +func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[string]string, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) - fmt.Fprintf(out, "Processing checksums\n") + fmt.Fprintf(out, sf.FormatStatus("Processing checksums")) imgList, err := srv.getImageList(localRepo) if err != nil { return err } - fmt.Fprintf(out, "Sending image list\n") + fmt.Fprintf(out, sf.FormatStatus("Sending image list")) repoData, err := srv.registry.PushImageJsonIndex(name, imgList, false) if err != nil { @@ -491,18 +491,18 @@ func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[stri // FIXME: Send only needed images for _, ep := range repoData.Endpoints { - fmt.Fprintf(out, "Pushing repository %s to %s (%d tags)\r\n", name, ep, len(localRepo)) + fmt.Fprintf(out, sf.FormatStatus("Pushing repository %s to %s (%d tags)"), name, ep, len(localRepo)) // For each image within the repo, push them for _, elem := range imgList { if _, exists := repoData.ImgList[elem.Id]; exists { - fmt.Fprintf(out, "Image %s already on registry, skipping\n", name) + fmt.Fprintf(out, sf.FormatStatus("Image %s already on registry, skipping"), name) continue } - if err := srv.pushImage(out, name, elem.Id, ep, repoData.Tokens); err != nil { + if err := srv.pushImage(out, name, elem.Id, ep, repoData.Tokens, sf); err != nil { // FIXME: Continue on error? return err } - fmt.Fprintf(out, "Pushing tags for rev [%s] on {%s}\n", elem.Id, ep+"/users/"+name+"/"+elem.Tag) + fmt.Fprintf(out, sf.FormatStatus("Pushing tags for rev [%s] on {%s}"), elem.Id, ep+"/users/"+name+"/"+elem.Tag) if err := srv.registry.PushRegistryTag(name, elem.Id, elem.Tag, ep, repoData.Tokens); err != nil { return err } @@ -515,13 +515,13 @@ func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[stri return nil } -func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []string) error { +func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []string, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) jsonRaw, err := ioutil.ReadFile(path.Join(srv.runtime.graph.Root, imgId, "json")) if err != nil { return fmt.Errorf("Error while retreiving the path for {%s}: %s", imgId, err) } - fmt.Fprintf(out, "Pushing %s\r\n", imgId) + fmt.Fprintf(out, sf.FormatStatus("Pushing %s"), imgId) // Make sure we have the image's checksum checksum, err := srv.getChecksum(imgId) @@ -536,7 +536,7 @@ func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []st // Send the json if err := srv.registry.PushImageJsonRegistry(imgData, jsonRaw, ep, token); err != nil { if err == registry.ErrAlreadyExists { - fmt.Fprintf(out, "Image %s already uploaded ; skipping\n", imgData.Id) + fmt.Fprintf(out, sf.FormatStatus("Image %s already uploaded ; skipping"), imgData.Id) return nil } return err @@ -569,20 +569,20 @@ func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []st } // Send the layer - if err := srv.registry.PushImageLayerRegistry(imgData.Id, utils.ProgressReader(layerData, int(layerData.Size), out, "", false), ep, token); err != nil { + if err := srv.registry.PushImageLayerRegistry(imgData.Id, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("", "%v/%v (%v)"), sf), ep, token); err != nil { return err } return nil } -func (srv *Server) ImagePush(name, registry string, out io.Writer) error { +func (srv *Server) ImagePush(name, registry string, out io.Writer, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) img, err := srv.runtime.graph.Get(name) if err != nil { - fmt.Fprintf(out, "The push refers to a repository [%s] (len: %d)\n", name, len(srv.runtime.repositories.Repositories[name])) + fmt.Fprintf(out, sf.FormatStatus("The push refers to a repository [%s] (len: %d)"), name, len(srv.runtime.repositories.Repositories[name])) // If it fails, try to get the repository if localRepo, exists := srv.runtime.repositories.Repositories[name]; exists { - if err := srv.pushRepository(out, name, localRepo); err != nil { + if err := srv.pushRepository(out, name, localRepo, sf); err != nil { return err } return nil @@ -590,14 +590,14 @@ func (srv *Server) ImagePush(name, registry string, out io.Writer) error { return err } - fmt.Fprintf(out, "The push refers to an image: [%s]\n", name) - if err := srv.pushImage(out, name, img.Id, registry, nil); err != nil { + fmt.Fprintf(out, sf.FormatStatus("The push refers to an image: [%s]"), name) + if err := srv.pushImage(out, name, img.Id, registry, nil, sf); err != nil { return err } return nil } -func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer) error { +func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Writer, sf *utils.StreamFormatter) error { var archive io.Reader var resp *http.Response @@ -606,21 +606,21 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write } else { u, err := url.Parse(src) if err != nil { - fmt.Fprintf(out, "Error: %s\n", err) + return err } if u.Scheme == "" { u.Scheme = "http" u.Host = src u.Path = "" } - fmt.Fprintf(out, "Downloading from %s\n", u) + fmt.Fprintf(out, sf.FormatStatus("Downloading from %s"), u) // Download with curl (pretty progress bar) // If curl is not available, fallback to http.Get() resp, err = utils.Download(u.String(), out) if err != nil { return err } - archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, "Importing %v/%v (%v)\r", false) + archive = utils.ProgressReader(resp.Body, int(resp.ContentLength), out, sf.FormatProgress("Importing", "%v/%v (%v)"), sf) } img, err := srv.runtime.graph.Create(archive, nil, "Imported from "+src, "", nil) if err != nil { @@ -632,7 +632,7 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write return err } } - fmt.Fprintf(out, "%s\n", img.ShortId()) + fmt.Fprintf(out, sf.FormatStatus(img.ShortId())) return nil } diff --git a/utils/utils.go b/utils/utils.go index 8588c52478..ec05c657e3 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -69,7 +69,7 @@ type progressReader struct { readProgress int // How much has been read so far (bytes) lastUpdate int // How many bytes read at least update template string // Template to print. Default "%v/%v (%v)" - json bool + sf *StreamFormatter } func (r *progressReader) Read(p []byte) (n int, err error) { @@ -93,7 +93,7 @@ func (r *progressReader) Read(p []byte) (n int, err error) { } // Send newline when complete if err != nil { - fmt.Fprintf(r.output, FormatStatus("", r.json)) + fmt.Fprintf(r.output, r.sf.FormatStatus("")) } return read, err @@ -101,11 +101,11 @@ func (r *progressReader) Read(p []byte) (n int, err error) { func (r *progressReader) Close() error { return io.ReadCloser(r.reader).Close() } -func ProgressReader(r io.ReadCloser, size int, output io.Writer, template string, json bool) *progressReader { +func ProgressReader(r io.ReadCloser, size int, output io.Writer, template string, sf *StreamFormatter) *progressReader { if template == "" { - template = "%v/%v (%v)\r" + template = "%v/%v (%v)" } - return &progressReader{r, NewWriteFlusher(output), size, 0, 0, template, json} + return &progressReader{r, NewWriteFlusher(output), size, 0, 0, template, sf} } // HumanDuration returns a human-readable approximation of a duration @@ -557,25 +557,41 @@ func NewWriteFlusher(w io.Writer) *WriteFlusher { return &WriteFlusher{w: w, flusher: flusher} } -func FormatStatus(str string, json bool) string { - if json { +type StreamFormatter struct { + json bool + used bool +} + +func NewStreamFormatter(json bool) *StreamFormatter { + return &StreamFormatter{json, false} +} + +func (sf *StreamFormatter) FormatStatus(str string) string { + sf.used = true + if sf.json { return "{\"status\" : \"" + str + "\"}" } return str + "\r\n" } -func FormatError(str string, json bool) string { - if json { - return "{\"error\" : \"" + str + "\"}" +func (sf *StreamFormatter) FormatError(err error) string { + sf.used = true + if sf.json { + return "{\"error\" : \"" + err.Error() + "\"}" } - return "Error: " + str + "\r\n" + return "Error: " + err.Error() + "\r\n" } -func FormatProgress(str string, json bool) string { - if json { +func (sf *StreamFormatter) FormatProgress(action, str string) string { + sf.used = true + if sf.json { return "{\"progress\" : \"" + str + "\"}" } - return "Downloading " + str + "\r" + return action + " " + str + "\r" +} + +func (sf *StreamFormatter) Used() bool { + return sf.used } From 14212930e40439d0cfc635d56e084736867f9e30 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sat, 25 May 2013 15:51:26 +0000 Subject: [PATCH 06/79] ensure valid json --- commands.go | 7 +------ server.go | 2 +- utils/utils.go | 24 +++++++++++++++++++++--- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/commands.go b/commands.go index 01ab8a334f..7a0a5be3ee 100644 --- a/commands.go +++ b/commands.go @@ -1258,14 +1258,9 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e } if resp.Header.Get("Content-Type") == "application/json" { - type Message struct { - Status string `json:"status,omitempty"` - Progress string `json:"progress,omitempty"` - Error string `json:"error,omitempty"` - } dec := json.NewDecoder(resp.Body) for { - var m Message + var m utils.JsonMessage if err := dec.Decode(&m); err == io.EOF { break } else if err != nil { diff --git a/server.go b/server.go index 3353796475..6ebf337dd0 100644 --- a/server.go +++ b/server.go @@ -368,7 +368,7 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, sf *ut success := false for _, ep := range repoData.Endpoints { if err := srv.pullImage(out, img.Id, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil { - fmt.Fprintf(out, sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint\n"), askedTag, err) + fmt.Fprintf(out, sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint"), askedTag, err) continue } success = true diff --git a/utils/utils.go b/utils/utils.go index ec05c657e3..1fce76e5aa 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/sha256" "encoding/hex" + "encoding/json" "errors" "fmt" "index/suffixarray" @@ -557,6 +558,12 @@ func NewWriteFlusher(w io.Writer) *WriteFlusher { return &WriteFlusher{w: w, flusher: flusher} } +type JsonMessage struct { + Status string `json:"status,omitempty"` + Progress string `json:"progress,omitempty"` + Error string `json:"error,omitempty"` +} + type StreamFormatter struct { json bool used bool @@ -569,7 +576,11 @@ func NewStreamFormatter(json bool) *StreamFormatter { func (sf *StreamFormatter) FormatStatus(str string) string { sf.used = true if sf.json { - return "{\"status\" : \"" + str + "\"}" + b, err := json.Marshal(&JsonMessage{Status:str}); + if err != nil { + return sf.FormatError(err) + } + return string(b) } return str + "\r\n" } @@ -577,7 +588,10 @@ func (sf *StreamFormatter) FormatStatus(str string) string { func (sf *StreamFormatter) FormatError(err error) string { sf.used = true if sf.json { - return "{\"error\" : \"" + err.Error() + "\"}" + if b, err := json.Marshal(&JsonMessage{Error:err.Error()}); err == nil { + return string(b) + } + return "{\"error\":\"format error\"}" } return "Error: " + err.Error() + "\r\n" } @@ -585,7 +599,11 @@ func (sf *StreamFormatter) FormatError(err error) string { func (sf *StreamFormatter) FormatProgress(action, str string) string { sf.used = true if sf.json { - return "{\"progress\" : \"" + str + "\"}" + b, err := json.Marshal(&JsonMessage{Progress:str}) + if err != nil { + return sf.FormatError(err) + } + return string(b) } return action + " " + str + "\r" } From 5a36efb61fae88a7fe71f67a6b1f8b9da6468014 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Sun, 26 May 2013 23:45:45 +0000 Subject: [PATCH 07/79] fix json encoding, and use less casts --- api.go | 8 ++++---- graph.go | 3 ++- server.go | 34 +++++++++++++++++----------------- utils/utils.go | 34 ++++++++++++++++++---------------- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/api.go b/api.go index 55fb8d5a66..c5472fa2c2 100644 --- a/api.go +++ b/api.go @@ -297,7 +297,7 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht registry := r.Form.Get("registry") if err := srv.ImagePull(image, tag, registry, w, sf); err != nil { if sf.Used() { - fmt.Fprintf(w, sf.FormatError(err)) + w.Write(sf.FormatError(err)) return nil } return err @@ -305,7 +305,7 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht } else { //import if err := srv.ImageImport(src, repo, tag, r.Body, w, sf); err != nil { if sf.Used() { - fmt.Fprintf(w, sf.FormatError(err)) + w.Write(sf.FormatError(err)) return nil } return err @@ -349,7 +349,7 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht sf := utils.NewStreamFormatter(version > 1.0) if err := srv.ImageInsert(name, url, path, w, sf); err != nil { if sf.Used() { - fmt.Fprintf(w, sf.FormatError(err)) + w.Write(sf.FormatError(err)) return nil } return err @@ -373,7 +373,7 @@ func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http sf := utils.NewStreamFormatter(version > 1.0) if err := srv.ImagePush(name, registry, w, sf); err != nil { if sf.Used() { - fmt.Fprintf(w, sf.FormatError(err)) + w.Write(sf.FormatError(err)) return nil } return err diff --git a/graph.go b/graph.go index 0090d51636..befb5ace5e 100644 --- a/graph.go +++ b/graph.go @@ -165,7 +165,8 @@ func (graph *Graph) TempLayerArchive(id string, compression Compression, output if err != nil { return nil, err } - return NewTempArchive(utils.ProgressReader(ioutil.NopCloser(archive), 0, output, "Buffering to disk %v/%v (%v)", utils.NewStreamFormatter(false)), tmp.Root) + sf := utils.NewStreamFormatter(false) + return NewTempArchive(utils.ProgressReader(ioutil.NopCloser(archive), 0, output, sf.FormatProgress("Buffering to disk", "%v/%v (%v)"), sf), tmp.Root) } // Mktemp creates a temporary sub-directory inside the graph's filesystem. diff --git a/server.go b/server.go index 6ebf337dd0..8799c6dc51 100644 --- a/server.go +++ b/server.go @@ -99,7 +99,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils. if err != nil { return err } - fmt.Fprintf(out, sf.FormatStatus("%s"), img.Id) + out.Write(sf.FormatStatus(img.Id)) return nil } @@ -301,7 +301,7 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri // FIXME: Launch the getRemoteImage() in goroutines for _, id := range history { if !srv.runtime.graph.Exists(id) { - fmt.Fprintf(out, sf.FormatStatus("Pulling %s metadata"), id) + out.Write(sf.FormatStatus("Pulling %s metadata", id)) imgJson, err := srv.registry.GetRemoteImageJson(id, registry, token) if err != nil { // FIXME: Keep goging in case of error? @@ -313,7 +313,7 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri } // Get the layer - fmt.Fprintf(out, sf.FormatStatus("Pulling %s fs layer"), id) + out.Write(sf.FormatStatus("Pulling %s fs layer", id)) layer, contentLength, err := srv.registry.GetRemoteImageLayer(img.Id, registry, token) if err != nil { return err @@ -327,7 +327,7 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri } func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, sf *utils.StreamFormatter) error { - fmt.Fprintf(out, sf.FormatStatus("Pulling repository %s from %s"), remote, auth.IndexServerAddress()) + out.Write(sf.FormatStatus("Pulling repository %s from %s", remote, auth.IndexServerAddress())) repoData, err := srv.registry.GetRepositoryData(remote) if err != nil { return err @@ -364,11 +364,11 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string, sf *ut utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.Id) continue } - fmt.Fprintf(out, sf.FormatStatus("Pulling image %s (%s) from %s"), img.Id, img.Tag, remote) + out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.Id, img.Tag, remote)) success := false for _, ep := range repoData.Endpoints { if err := srv.pullImage(out, img.Id, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil { - fmt.Fprintf(out, sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint"), askedTag, err) + out.Write(sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint", askedTag, err)) continue } success = true @@ -477,12 +477,12 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]*registry.ImgDat func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[string]string, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) - fmt.Fprintf(out, sf.FormatStatus("Processing checksums")) + out.Write(sf.FormatStatus("Processing checksums")) imgList, err := srv.getImageList(localRepo) if err != nil { return err } - fmt.Fprintf(out, sf.FormatStatus("Sending image list")) + out.Write(sf.FormatStatus("Sending image list")) repoData, err := srv.registry.PushImageJsonIndex(name, imgList, false) if err != nil { @@ -491,18 +491,18 @@ func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[stri // FIXME: Send only needed images for _, ep := range repoData.Endpoints { - fmt.Fprintf(out, sf.FormatStatus("Pushing repository %s to %s (%d tags)"), name, ep, len(localRepo)) + out.Write(sf.FormatStatus("Pushing repository %s to %s (%d tags)", name, ep, len(localRepo))) // For each image within the repo, push them for _, elem := range imgList { if _, exists := repoData.ImgList[elem.Id]; exists { - fmt.Fprintf(out, sf.FormatStatus("Image %s already on registry, skipping"), name) + out.Write(sf.FormatStatus("Image %s already on registry, skipping", name)) continue } if err := srv.pushImage(out, name, elem.Id, ep, repoData.Tokens, sf); err != nil { // FIXME: Continue on error? return err } - fmt.Fprintf(out, sf.FormatStatus("Pushing tags for rev [%s] on {%s}"), elem.Id, ep+"/users/"+name+"/"+elem.Tag) + out.Write(sf.FormatStatus("Pushing tags for rev [%s] on {%s}", elem.Id, ep+"/users/"+name+"/"+elem.Tag)) if err := srv.registry.PushRegistryTag(name, elem.Id, elem.Tag, ep, repoData.Tokens); err != nil { return err } @@ -521,7 +521,7 @@ func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []st if err != nil { return fmt.Errorf("Error while retreiving the path for {%s}: %s", imgId, err) } - fmt.Fprintf(out, sf.FormatStatus("Pushing %s"), imgId) + out.Write(sf.FormatStatus("Pushing %s", imgId)) // Make sure we have the image's checksum checksum, err := srv.getChecksum(imgId) @@ -536,7 +536,7 @@ func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []st // Send the json if err := srv.registry.PushImageJsonRegistry(imgData, jsonRaw, ep, token); err != nil { if err == registry.ErrAlreadyExists { - fmt.Fprintf(out, sf.FormatStatus("Image %s already uploaded ; skipping"), imgData.Id) + out.Write(sf.FormatStatus("Image %s already uploaded ; skipping", imgData.Id)) return nil } return err @@ -579,7 +579,7 @@ func (srv *Server) ImagePush(name, registry string, out io.Writer, sf *utils.Str out = utils.NewWriteFlusher(out) img, err := srv.runtime.graph.Get(name) if err != nil { - fmt.Fprintf(out, sf.FormatStatus("The push refers to a repository [%s] (len: %d)"), name, len(srv.runtime.repositories.Repositories[name])) + out.Write(sf.FormatStatus("The push refers to a repository [%s] (len: %d)", name, len(srv.runtime.repositories.Repositories[name]))) // If it fails, try to get the repository if localRepo, exists := srv.runtime.repositories.Repositories[name]; exists { if err := srv.pushRepository(out, name, localRepo, sf); err != nil { @@ -590,7 +590,7 @@ func (srv *Server) ImagePush(name, registry string, out io.Writer, sf *utils.Str return err } - fmt.Fprintf(out, sf.FormatStatus("The push refers to an image: [%s]"), name) + out.Write(sf.FormatStatus("The push refers to an image: [%s]", name)) if err := srv.pushImage(out, name, img.Id, registry, nil, sf); err != nil { return err } @@ -613,7 +613,7 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write u.Host = src u.Path = "" } - fmt.Fprintf(out, sf.FormatStatus("Downloading from %s"), u) + out.Write(sf.FormatStatus("Downloading from %s", u)) // Download with curl (pretty progress bar) // If curl is not available, fallback to http.Get() resp, err = utils.Download(u.String(), out) @@ -632,7 +632,7 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write return err } } - fmt.Fprintf(out, sf.FormatStatus(img.ShortId())) + out.Write(sf.FormatStatus(img.ShortId())) return nil } diff --git a/utils/utils.go b/utils/utils.go index 1fce76e5aa..64aa111717 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -94,7 +94,7 @@ func (r *progressReader) Read(p []byte) (n int, err error) { } // Send newline when complete if err != nil { - fmt.Fprintf(r.output, r.sf.FormatStatus("")) + r.output.Write(r.sf.FormatStatus("")) } return read, err @@ -102,11 +102,12 @@ func (r *progressReader) Read(p []byte) (n int, err error) { func (r *progressReader) Close() error { return io.ReadCloser(r.reader).Close() } -func ProgressReader(r io.ReadCloser, size int, output io.Writer, template string, sf *StreamFormatter) *progressReader { - if template == "" { - template = "%v/%v (%v)" +func ProgressReader(r io.ReadCloser, size int, output io.Writer, template []byte, sf *StreamFormatter) *progressReader { + tpl := string(template) + if tpl == "" { + tpl = "%v/%v (%v)" } - return &progressReader{r, NewWriteFlusher(output), size, 0, 0, template, sf} + return &progressReader{r, NewWriteFlusher(output), size, 0, 0, tpl, sf} } // HumanDuration returns a human-readable approximation of a duration @@ -573,39 +574,40 @@ func NewStreamFormatter(json bool) *StreamFormatter { return &StreamFormatter{json, false} } -func (sf *StreamFormatter) FormatStatus(str string) string { +func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte { sf.used = true + str := fmt.Sprintf(format, a...) if sf.json { b, err := json.Marshal(&JsonMessage{Status:str}); if err != nil { return sf.FormatError(err) } - return string(b) + return b } - return str + "\r\n" + return []byte(str + "\r\n") } -func (sf *StreamFormatter) FormatError(err error) string { +func (sf *StreamFormatter) FormatError(err error) []byte { sf.used = true if sf.json { if b, err := json.Marshal(&JsonMessage{Error:err.Error()}); err == nil { - return string(b) + return b } - return "{\"error\":\"format error\"}" + return []byte("{\"error\":\"format error\"}") } - return "Error: " + err.Error() + "\r\n" + return []byte("Error: " + err.Error() + "\r\n") } -func (sf *StreamFormatter) FormatProgress(action, str string) string { +func (sf *StreamFormatter) FormatProgress(action, str string) []byte { sf.used = true if sf.json { b, err := json.Marshal(&JsonMessage{Progress:str}) if err != nil { - return sf.FormatError(err) + return nil } - return string(b) + return b } - return action + " " + str + "\r" + return []byte(action + " " + str + "\r") } func (sf *StreamFormatter) Used() bool { From fbcd8503b3a29bdbb7a52d6433b0ab79877bc4ce Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 27 May 2013 16:07:05 +0000 Subject: [PATCH 08/79] remove hijack on the client in logs, and split stdout / stderr --- commands.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/commands.go b/commands.go index 6c4dcd14d6..097ece9fce 100644 --- a/commands.go +++ b/commands.go @@ -920,12 +920,10 @@ func (cli *DockerCli) CmdLogs(args ...string) error { return nil } - v := url.Values{} - v.Set("logs", "1") - v.Set("stdout", "1") - v.Set("stderr", "1") - - if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), false); err != nil { + if err := cli.stream("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stdout=1", nil, os.Stdout); err != nil { + return err + } + if err := cli.stream("POST", "/containers/"+cmd.Arg(0)+"/attach?logs=1&stderr=1", nil, os.Stderr); err != nil { return err } return nil From 8699805756d25602e2412173aac7364fbe9627c7 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 28 May 2013 15:49:57 +0000 Subject: [PATCH 09/79] documentation --- docs/sources/api/docker_remote_api.rst | 57 ++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index 4c8ebe847f..3920aba983 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -15,10 +15,17 @@ Docker Remote API - Default port in the docker deamon is 4243 - The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr -2. Endpoints +2. Version +========== + +The current verson of the API is 1.1 +Calling /images//insert is the same as calling /v1.1/images//insert +You can still call an old version of the api using /v1.0/images//insert + +3. Endpoints ============ -2.1 Containers +3.1 Containers -------------- List containers @@ -459,7 +466,7 @@ Remove a container :statuscode 500: server error -2.2 Images +3.2 Images ---------- List Images @@ -548,7 +555,19 @@ Create an image POST /images/create?fromImage=base HTTP/1.1 - **Example response**: + **Example response v1.1**: + + .. sourcecode:: http + + HTTP/1.1 200 OK + Content-Type: application/json + + {"status":"Pulling..."} + {"progress":"1/? (n/a)"} + {"error":"Invalid..."} + ... + + **Example response v1.0**: .. sourcecode:: http @@ -579,7 +598,19 @@ Insert a file in a image POST /images/test/insert?path=/usr&url=myurl HTTP/1.1 - **Example response**: + **Example response v1.1**: + + .. sourcecode:: http + + HTTP/1.1 200 OK + Content-Type: application/json + + {"status":"Inserting..."} + {"progress":"1/? (n/a)"} + {"error":"Invalid..."} + ... + + **Example response v1.0**: .. sourcecode:: http @@ -694,7 +725,19 @@ Push an image on the registry POST /images/test/push HTTP/1.1 - **Example response**: + **Example response v1.1**: + + .. sourcecode:: http + + HTTP/1.1 200 OK + Content-Type: application/json + + {"status":"Pushing..."} + {"progress":"1/? (n/a)"} + {"error":"Invalid..."} + ... + + **Example response v1.0**: .. sourcecode:: http @@ -800,7 +843,7 @@ Search images :statuscode 500: server error -2.3 Misc +3.3 Misc -------- Build an image from Dockerfile via stdin From 75d2244023cd39af17976c56225da6b5158ff68f Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 10:51:47 -0700 Subject: [PATCH 10/79] Update docker build UI --- commands.go | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/commands.go b/commands.go index e34c40f8cc..501dea6043 100644 --- a/commands.go +++ b/commands.go @@ -17,6 +17,7 @@ import ( "net/url" "os" "os/signal" + "path" "path/filepath" "reflect" "strconv" @@ -130,17 +131,12 @@ func (cli *DockerCli) CmdInsert(args ...string) error { } func (cli *DockerCli) CmdBuild(args ...string) error { - cmd := Subcmd("build", "[OPTIONS] [CONTEXT]", "Build an image from a Dockerfile") - fileName := cmd.String("f", "Dockerfile", "Use `file` as Dockerfile. Can be '-' for stdin") + cmd := Subcmd("build", "[CONTEXT]", "Build an image from a Dockerfile") if err := cmd.Parse(args); err != nil { return nil } - var ( - file io.ReadCloser - multipartBody io.Reader - err error - ) + var multipartBody io.Reader // Init the needed component for the Multipart buff := bytes.NewBuffer([]byte{}) @@ -148,17 +144,19 @@ func (cli *DockerCli) CmdBuild(args ...string) error { w := multipart.NewWriter(buff) boundary := strings.NewReader("\r\n--" + w.Boundary() + "--\r\n") - // Create a FormFile multipart for the Dockerfile - if *fileName == "-" { - file = os.Stdin - } else { - file, err = os.Open(*fileName) - if err != nil { - return err - } - defer file.Close() + dockerfile := "Dockerfile" + + if cmd.Arg(0) != "" { + dockerfile = path.Join(cmd.Arg(0), dockerfile) } - if wField, err := w.CreateFormFile("Dockerfile", *fileName); err != nil { + + // Create a FormFile multipart for the Dockerfile + file, err := os.Open(dockerfile) + if err != nil { + return err + } + defer file.Close() + if wField, err := w.CreateFormFile("Dockerfile", "Dockerfile"); err != nil { return err } else { io.Copy(wField, file) From 6cbc7757b2b4d068a98287754da552028fd62212 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 10:53:24 -0700 Subject: [PATCH 11/79] Fix issue with unknown instruction within docker build --- buildfile.go | 1 + 1 file changed, 1 insertion(+) diff --git a/buildfile.go b/buildfile.go index 23f2f47172..b9ca5696d5 100644 --- a/buildfile.go +++ b/buildfile.go @@ -337,6 +337,7 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:])) if !exists { fmt.Fprintf(b.out, "Skipping unknown instruction %s\n", strings.ToUpper(instruction)) + continue } ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface() if ret != nil { From c7af917d13c34c6a008df60fa45079fab32cea70 Mon Sep 17 00:00:00 2001 From: Roberto Gandolfo Hashioka Date: Wed, 29 May 2013 11:29:30 -0700 Subject: [PATCH 12/79] updated the running ssh service example with the video's transcription --- docs/sources/examples/running_ssh_service.rst | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/docs/sources/examples/running_ssh_service.rst b/docs/sources/examples/running_ssh_service.rst index f418b45266..b262266dec 100644 --- a/docs/sources/examples/running_ssh_service.rst +++ b/docs/sources/examples/running_ssh_service.rst @@ -20,8 +20,7 @@ minutes and not entirely smooth, but gives you a good idea.
- - + You can also get this sshd container by using :: @@ -30,3 +29,49 @@ You can also get this sshd container by using The password is 'screencast' +**Video's Transcription:** + +.. code-block:: bash + + # Hello! We are going to try and install openssh on a container and run it as a servic + # let's pull base to get a base ubuntu image. + $ docker pull base + # I had it so it was quick + # now let's connect using -i for interactive and with -t for terminal + # we execute /bin/bash to get a prompt. + $ docker run -i -t base /bin/bash + # now let's commit it + # which container was it? + $ docker ps -a |more + $ docker commit a30a3a2f2b130749995f5902f079dc6ad31ea0621fac595128ec59c6da07feea dhrp/sshd + # I gave the name dhrp/sshd for the container + # now we can run it again + $ docker run -d dhrp/sshd /usr/sbin/sshd -D # D for daemon mode + # is it running? + $ docker ps + # yes! + # let's stop it + $ docker stop 0ebf7cec294755399d063f4b1627980d4cbff7d999f0bc82b59c300f8536a562 + $ docker ps + # and reconnect, but now open a port to it + $ docker run -d -p 22 dhrp/sshd /usr/sbin/sshd -D + $ docker port b2b407cf22cf8e7fa3736fa8852713571074536b1d31def3fdfcd9fa4fd8c8c5 22 + # it has now given us a port to connect to + # we have to connect using a public ip of our host + $ hostname + $ ifconfig + $ ssh root@192.168.33.10 -p 49153 + # Ah! forgot to set root passwd + $ docker commit b2b407cf22cf8e7fa3736fa8852713571074536b1d31def3fdfcd9fa4fd8c8c5 dhrp/sshd + $ docker ps -a + $ docker run -i -t dhrp/sshd /bin/bash + $ passwd + $ exit + $ docker commit 9e863f0ca0af31c8b951048ba87641d67c382d08d655c2e4879c51410e0fedc1 dhrp/sshd + $ docker run -d -p 22 dhrp/sshd /usr/sbin/sshd -D + $ docker port a0aaa9558c90cf5c7782648df904a82365ebacce523e4acc085ac1213bfe2206 22 + $ ifconfig + $ ssh root@192.168.33.10 -p 49154 + # Thanks for watching, Thatcher thatcher@dotcloud.com + + From 33ea1483d5b89559e1fe9a9556e3ea757f673e16 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 11:43:29 -0700 Subject: [PATCH 13/79] Allow docker build from stdin --- commands.go | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/commands.go b/commands.go index 501dea6043..8e8e17df81 100644 --- a/commands.go +++ b/commands.go @@ -131,12 +131,16 @@ func (cli *DockerCli) CmdInsert(args ...string) error { } func (cli *DockerCli) CmdBuild(args ...string) error { - cmd := Subcmd("build", "[CONTEXT]", "Build an image from a Dockerfile") + cmd := Subcmd("build", "[CONTEXT|-]", "Build an image from a Dockerfile") if err := cmd.Parse(args); err != nil { return nil } - var multipartBody io.Reader + var ( + multipartBody io.Reader + file io.ReadCloser + contextPath string + ) // Init the needed component for the Multipart buff := bytes.NewBuffer([]byte{}) @@ -146,16 +150,23 @@ func (cli *DockerCli) CmdBuild(args ...string) error { dockerfile := "Dockerfile" - if cmd.Arg(0) != "" { + if cmd.Arg(0) != "" && cmd.Arg(0) != "-" { + contextPath = cmd.Arg(0) dockerfile = path.Join(cmd.Arg(0), dockerfile) } + if cmd.Arg(0) != "-" { + f, err := os.Open(dockerfile) + if err != nil { + return err + } + defer f.Close() + file = f + } else { + contextPath = cmd.Arg(1) + file = os.Stdin + } // Create a FormFile multipart for the Dockerfile - file, err := os.Open(dockerfile) - if err != nil { - return err - } - defer file.Close() if wField, err := w.CreateFormFile("Dockerfile", "Dockerfile"); err != nil { return err } else { @@ -166,14 +177,14 @@ func (cli *DockerCli) CmdBuild(args ...string) error { compression := Bzip2 // Create a FormFile multipart for the context if needed - if cmd.Arg(0) != "" { + if contextPath != "" { // FIXME: Use NewTempArchive in order to have the size and avoid too much memory usage? - context, err := Tar(cmd.Arg(0), compression) + context, err := Tar(contextPath, compression) if err != nil { return err } // NOTE: Do this in case '.' or '..' is input - absPath, err := filepath.Abs(cmd.Arg(0)) + absPath, err := filepath.Abs(contextPath) if err != nil { return err } @@ -193,7 +204,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error { return err } req.Header.Set("Content-Type", w.FormDataContentType()) - if cmd.Arg(0) != "" { + if contextPath != "" { req.Header.Set("X-Docker-Context-Compression", compression.Flag()) fmt.Println("Uploading Context...") } From d97fff60a9275324290bb01b921c9b6b0967a4fd Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 11:50:49 -0700 Subject: [PATCH 14/79] Update docker build docs --- docs/sources/commandline/command/build.rst | 32 ++++++++++++++++++++-- docs/sources/use/builder.rst | 10 +++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/sources/commandline/command/build.rst b/docs/sources/commandline/command/build.rst index a8d2093a5b..0cb6463e4c 100644 --- a/docs/sources/commandline/command/build.rst +++ b/docs/sources/commandline/command/build.rst @@ -8,6 +8,32 @@ :: - Usage: docker build - - Example: cat Dockerfile | docker build - - Build a new image from the Dockerfile passed via stdin + Usage: docker build [CONTEXT|-] + Build a new image from a Dockerfile + +Examples +-------- + +.. code-block:: bash + + docker build + +This will take the local Dockerfile without context + +.. code-block:: bash + + docker build - + +This will read a Dockerfile form Stdin without context + +.. code-block:: bash + + docker build . + +This will take the local Dockerfile and set the current directory as context + +.. code-block:: bash + + docker build - . + +This will read a Dockerfile from Stdin and set the current directory as context diff --git a/docs/sources/use/builder.rst b/docs/sources/use/builder.rst index 4e53ed4a79..abd5b9ecb1 100644 --- a/docs/sources/use/builder.rst +++ b/docs/sources/use/builder.rst @@ -125,8 +125,14 @@ curl was installed within the image. .. note:: The path must include the file name. -.. note:: - This instruction has temporarily disabled +2.8 ADD +------- + + ``ADD `` + +The `ADD` instruction will insert the files from the `` path of the context into `` path +of the container. +The context must be set in order to use this instruction. (see examples) 3. Dockerfile Examples ====================== From 92939569ab06d13cd179d6e998ef9576d3921bb6 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 11:53:44 -0700 Subject: [PATCH 15/79] Update build doc --- docs/sources/commandline/command/build.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sources/commandline/command/build.rst b/docs/sources/commandline/command/build.rst index 0cb6463e4c..f7df8cbbc3 100644 --- a/docs/sources/commandline/command/build.rst +++ b/docs/sources/commandline/command/build.rst @@ -2,9 +2,9 @@ :description: Build a new image from the Dockerfile passed via stdin :keywords: build, docker, container, documentation -======================================================== -``build`` -- Build a container from Dockerfile via stdin -======================================================== +================================================ +``build`` -- Build a container from a Dockerfile +================================================ :: From ae0d555022411025607acce43ea1929bafd7174a Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 14:37:03 -0700 Subject: [PATCH 16/79] Fix autorun issue within docker build --- buildfile.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/buildfile.go b/buildfile.go index b9ca5696d5..0dd9bc049c 100644 --- a/buildfile.go +++ b/buildfile.go @@ -95,10 +95,12 @@ func (b *buildFile) CmdRun(args string) error { return err } - cmd, env := b.config.Cmd, b.config.Env + cmd := b.config.Cmd b.config.Cmd = nil MergeConfig(b.config, config) + utils.Debugf("Commang to be executed: %v", b.config.Cmd) + if cache, err := b.srv.ImageGetCached(b.image, config); err != nil { return err } else if cache != nil { @@ -111,8 +113,11 @@ func (b *buildFile) CmdRun(args string) error { if err != nil { return err } - b.config.Cmd, b.config.Env = cmd, env - return b.commit(cid) + if err := b.commit(cid, cmd); err != nil { + return err + } + b.config.Cmd = cmd + return nil } func (b *buildFile) CmdEnv(args string) error { @@ -153,6 +158,7 @@ func (b *buildFile) CmdExpose(args string) error { } func (b *buildFile) CmdInsert(args string) error { + if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to insert") } @@ -169,6 +175,7 @@ func (b *buildFile) CmdInsert(args string) error { } defer file.Body.Close() + cmd := b.config.Cmd b.config.Cmd = []string{"echo", "INSERT", sourceUrl, "in", destPath} cid, err := b.run() if err != nil { @@ -184,7 +191,7 @@ func (b *buildFile) CmdInsert(args string) error { return err } - return b.commit(cid) + return b.commit(cid, cmd) } func (b *buildFile) CmdAdd(args string) error { @@ -198,6 +205,7 @@ func (b *buildFile) CmdAdd(args string) error { orig := strings.Trim(tmp[0], " ") dest := strings.Trim(tmp[1], " ") + cmd := b.config.Cmd b.config.Cmd = []string{"echo", "PUSH", orig, "in", dest} cid, err := b.run() if err != nil { @@ -236,7 +244,7 @@ func (b *buildFile) CmdAdd(args string) error { } } - return b.commit(cid) + return b.commit(cid, cmd) } func (b *buildFile) run() (string, error) { @@ -265,7 +273,8 @@ func (b *buildFile) run() (string, error) { return c.Id, nil } -func (b *buildFile) commit(id string) error { +// Commit the container with the autorun command +func (b *buildFile) commit(id string, autoCmd []string) error { if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to commit") } @@ -286,8 +295,11 @@ func (b *buildFile) commit(id string) error { return fmt.Errorf("An error occured while creating the container") } + // Note: Actually copy the struct + autoConfig := *b.config + autoConfig.Cmd = autoCmd // Commit the container - image, err := b.builder.Commit(container, "", "", "", b.maintainer, nil) + image, err := b.builder.Commit(container, "", "", "", b.maintainer, &autoConfig) if err != nil { return err } @@ -347,7 +359,7 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { fmt.Fprintf(b.out, "===> %v\n", b.image) } if b.needCommit { - if err := b.commit(""); err != nil { + if err := b.commit("", nil); err != nil { return "", err } } From b6165daa775bbf20451ecbe570ab0fb85ad35128 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 15:03:00 -0700 Subject: [PATCH 17/79] Create a layer for each operation (expose, cmd, etc) --- buildfile.go | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/buildfile.go b/buildfile.go index 0dd9bc049c..05dafe53e1 100644 --- a/buildfile.go +++ b/buildfile.go @@ -32,8 +32,6 @@ type buildFile struct { tmpContainers map[string]struct{} tmpImages map[string]struct{} - needCommit bool - out io.Writer } @@ -81,9 +79,8 @@ func (b *buildFile) CmdFrom(name string) error { } func (b *buildFile) CmdMaintainer(name string) error { - b.needCommit = true b.maintainer = name - return nil + return b.commit("", b.config.Cmd, fmt.Sprintf("MAINTAINER %s", name)) } func (b *buildFile) CmdRun(args string) error { @@ -113,7 +110,7 @@ func (b *buildFile) CmdRun(args string) error { if err != nil { return err } - if err := b.commit(cid, cmd); err != nil { + if err := b.commit(cid, cmd, "run"); err != nil { return err } b.config.Cmd = cmd @@ -121,7 +118,6 @@ func (b *buildFile) CmdRun(args string) error { } func (b *buildFile) CmdEnv(args string) error { - b.needCommit = true tmp := strings.SplitN(args, " ", 2) if len(tmp) != 2 { return fmt.Errorf("Invalid ENV format") @@ -136,29 +132,25 @@ func (b *buildFile) CmdEnv(args string) error { } } b.config.Env = append(b.config.Env, key+"="+value) - return nil + return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s=%s", key, value)) } func (b *buildFile) CmdCmd(args string) error { - b.needCommit = true var cmd []string if err := json.Unmarshal([]byte(args), &cmd); err != nil { utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err) - b.config.Cmd = []string{"/bin/sh", "-c", args} - } else { - b.config.Cmd = cmd + cmd = []string{"/bin/sh", "-c", args} } - return nil + return b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)) } func (b *buildFile) CmdExpose(args string) error { ports := strings.Split(args, " ") b.config.PortSpecs = append(ports, b.config.PortSpecs...) - return nil + return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports)) } func (b *buildFile) CmdInsert(args string) error { - if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to insert") } @@ -176,7 +168,7 @@ func (b *buildFile) CmdInsert(args string) error { defer file.Body.Close() cmd := b.config.Cmd - b.config.Cmd = []string{"echo", "INSERT", sourceUrl, "in", destPath} + b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) INSERT %s in %s", sourceUrl, destPath)} cid, err := b.run() if err != nil { return err @@ -190,8 +182,7 @@ func (b *buildFile) CmdInsert(args string) error { if err := container.Inject(file.Body, destPath); err != nil { return err } - - return b.commit(cid, cmd) + return b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)) } func (b *buildFile) CmdAdd(args string) error { @@ -206,7 +197,7 @@ func (b *buildFile) CmdAdd(args string) error { dest := strings.Trim(tmp[1], " ") cmd := b.config.Cmd - b.config.Cmd = []string{"echo", "PUSH", orig, "in", dest} + b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) ADD %s in %s", orig, dest)} cid, err := b.run() if err != nil { return err @@ -243,8 +234,7 @@ func (b *buildFile) CmdAdd(args string) error { return err } } - - return b.commit(cid, cmd) + return b.commit(cid, cmd, fmt.Sprintf("ADD %s in %s", orig, dest)) } func (b *buildFile) run() (string, error) { @@ -274,20 +264,18 @@ func (b *buildFile) run() (string, error) { } // Commit the container with the autorun command -func (b *buildFile) commit(id string, autoCmd []string) error { +func (b *buildFile) commit(id string, autoCmd []string, comment string) error { if b.image == "" { return fmt.Errorf("Please provide a source image with `from` prior to commit") } b.config.Image = b.image if id == "" { - cmd := b.config.Cmd - b.config.Cmd = []string{"true"} + b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment} if cid, err := b.run(); err != nil { return err } else { id = cid } - b.config.Cmd = cmd } container := b.runtime.Get(id) @@ -305,7 +293,6 @@ func (b *buildFile) commit(id string, autoCmd []string) error { } b.tmpImages[image.Id] = struct{}{} b.image = image.Id - b.needCommit = false return nil } @@ -358,11 +345,6 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { fmt.Fprintf(b.out, "===> %v\n", b.image) } - if b.needCommit { - if err := b.commit("", nil); err != nil { - return "", err - } - } if b.image != "" { // The build is successful, keep the temporary containers and images for i := range b.tmpImages { From 560a74af1562de007ba487e102fd00a2f658e6a0 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 16:10:11 -0700 Subject: [PATCH 18/79] Fix cache miss issue within docker build --- buildfile.go | 23 ++++++++++++++++++++--- server.go | 19 ++----------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/buildfile.go b/buildfile.go index 05dafe53e1..60a975c8de 100644 --- a/buildfile.go +++ b/buildfile.go @@ -98,12 +98,14 @@ func (b *buildFile) CmdRun(args string) error { utils.Debugf("Commang to be executed: %v", b.config.Cmd) - if cache, err := b.srv.ImageGetCached(b.image, config); err != nil { + if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil { return err } else if cache != nil { - utils.Debugf("Use cached version") + utils.Debugf("[BUILDER] Use cached version") b.image = cache.Id return nil + } else { + utils.Debugf("[BUILDER] Cache miss") } cid, err := b.run() @@ -182,7 +184,11 @@ func (b *buildFile) CmdInsert(args string) error { if err := container.Inject(file.Body, destPath); err != nil { return err } - return b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)) + if err := b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)); err != nil { + return err + } + b.config.Cmd = cmd + return nil } func (b *buildFile) CmdAdd(args string) error { @@ -271,6 +277,17 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { b.config.Image = b.image if id == "" { b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment} + + if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil { + return err + } else if cache != nil { + utils.Debugf("[BUILDER] Use cached version") + b.image = cache.Id + return nil + } else { + utils.Debugf("[BUILDER] Cache miss") + } + if cid, err := b.run(); err != nil { return err } else { diff --git a/server.go b/server.go index 0440b0a8a4..0125d2f0c1 100644 --- a/server.go +++ b/server.go @@ -720,28 +720,13 @@ func (srv *Server) ImageDelete(name string) error { } func (srv *Server) ImageGetCached(imgId string, config *Config) (*Image, error) { - - // Retrieve all images - images, err := srv.runtime.graph.All() + byParent, err := srv.runtime.graph.ByParent() if err != nil { return nil, err } - // Store the tree in a map of map (map[parentId][childId]) - imageMap := make(map[string]map[string]struct{}) - for _, img := range images { - if _, exists := imageMap[img.Parent]; !exists { - imageMap[img.Parent] = make(map[string]struct{}) - } - imageMap[img.Parent][img.Id] = struct{}{} - } - // Loop on the children of the given image and check the config - for elem := range imageMap[imgId] { - img, err := srv.runtime.graph.Get(elem) - if err != nil { - return nil, err - } + for _, img := range byParent[imgId] { if CompareConfig(&img.ContainerConfig, config) { return img, nil } From 881fdc59edf39ba8d87b44b05db7fcd95661d083 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 17:04:46 -0700 Subject: [PATCH 19/79] Remove cache opti that cause wrong cache miss --- server.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/server.go b/server.go index 0125d2f0c1..0440b0a8a4 100644 --- a/server.go +++ b/server.go @@ -720,13 +720,28 @@ func (srv *Server) ImageDelete(name string) error { } func (srv *Server) ImageGetCached(imgId string, config *Config) (*Image, error) { - byParent, err := srv.runtime.graph.ByParent() + + // Retrieve all images + images, err := srv.runtime.graph.All() if err != nil { return nil, err } + // Store the tree in a map of map (map[parentId][childId]) + imageMap := make(map[string]map[string]struct{}) + for _, img := range images { + if _, exists := imageMap[img.Parent]; !exists { + imageMap[img.Parent] = make(map[string]struct{}) + } + imageMap[img.Parent][img.Id] = struct{}{} + } + // Loop on the children of the given image and check the config - for _, img := range byParent[imgId] { + for elem := range imageMap[imgId] { + img, err := srv.runtime.graph.Get(elem) + if err != nil { + return nil, err + } if CompareConfig(&img.ContainerConfig, config) { return img, nil } From faafbf211899bc28e7e21e76de051d87ef5b5cd2 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 17:58:05 -0700 Subject: [PATCH 20/79] Fix ADD behavior on single files --- buildfile.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/buildfile.go b/buildfile.go index 60a975c8de..fa19ab2392 100644 --- a/buildfile.go +++ b/buildfile.go @@ -213,13 +213,17 @@ func (b *buildFile) CmdAdd(args string) error { if container == nil { return fmt.Errorf("Error while creating the container (CmdAdd)") } - - if err := os.MkdirAll(path.Join(container.rwPath(), dest), 0700); err != nil { + if err := container.EnsureMounted(); err != nil { return err } + defer container.Unmount() origPath := path.Join(b.context, orig) - destPath := path.Join(container.rwPath(), dest) + destPath := path.Join(container.RootfsPath(), dest) + + if err := os.MkdirAll(path.Dir(destPath), 0700); err != nil { + return err + } fi, err := os.Stat(origPath) if err != nil { From dcab408f6a047d5a4ccac0d3999d8c896f0a63dc Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 29 May 2013 18:14:50 -0700 Subject: [PATCH 21/79] Fixed phrasing, typos and formatting in 'docker build' --- buildfile.go | 6 +++--- commands.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/buildfile.go b/buildfile.go index fa19ab2392..805ebb4fbb 100644 --- a/buildfile.go +++ b/buildfile.go @@ -96,7 +96,7 @@ func (b *buildFile) CmdRun(args string) error { b.config.Cmd = nil MergeConfig(b.config, config) - utils.Debugf("Commang to be executed: %v", b.config.Cmd) + utils.Debugf("Command to be executed: %v", b.config.Cmd) if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil { return err @@ -197,7 +197,7 @@ func (b *buildFile) CmdAdd(args string) error { } tmp := strings.SplitN(args, " ", 2) if len(tmp) != 2 { - return fmt.Errorf("Invalid INSERT format") + return fmt.Errorf("Invalid ADD format") } orig := strings.Trim(tmp[0], " ") dest := strings.Trim(tmp[1], " ") @@ -371,7 +371,7 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { for i := range b.tmpImages { delete(b.tmpImages, i) } - fmt.Fprintf(b.out, "Build success.\n Image id:\n%s\n", b.image) + fmt.Fprintf(b.out, "Build successful.\n===> %s\n", b.image) return b.image, nil } for i := range b.tmpContainers { diff --git a/commands.go b/commands.go index 8e8e17df81..6cca487851 100644 --- a/commands.go +++ b/commands.go @@ -131,7 +131,7 @@ func (cli *DockerCli) CmdInsert(args ...string) error { } func (cli *DockerCli) CmdBuild(args ...string) error { - cmd := Subcmd("build", "[CONTEXT|-]", "Build an image from a Dockerfile") + cmd := Subcmd("build", "PATH | -", "Build a new container image from the source code at PATH") if err := cmd.Parse(args); err != nil { return nil } From fc864d2f0f2814be87984cefec66719c6d95d802 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 29 May 2013 18:18:57 -0700 Subject: [PATCH 22/79] Simplified syntax of 'docker build': 'docker build PATH | -' --- commands.go | 55 +++++++++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/commands.go b/commands.go index 6cca487851..67b8e917f5 100644 --- a/commands.go +++ b/commands.go @@ -135,6 +135,10 @@ func (cli *DockerCli) CmdBuild(args ...string) error { if err := cmd.Parse(args); err != nil { return nil } + if cmd.NArg() != 1 { + cmd.Usage() + return nil + } var ( multipartBody io.Reader @@ -148,43 +152,26 @@ func (cli *DockerCli) CmdBuild(args ...string) error { w := multipart.NewWriter(buff) boundary := strings.NewReader("\r\n--" + w.Boundary() + "--\r\n") - dockerfile := "Dockerfile" - - if cmd.Arg(0) != "" && cmd.Arg(0) != "-" { - contextPath = cmd.Arg(0) - dockerfile = path.Join(cmd.Arg(0), dockerfile) - } - if cmd.Arg(0) != "-" { - f, err := os.Open(dockerfile) - if err != nil { - return err - } - defer f.Close() - file = f - } else { - contextPath = cmd.Arg(1) - file = os.Stdin - } - - // Create a FormFile multipart for the Dockerfile - if wField, err := w.CreateFormFile("Dockerfile", "Dockerfile"); err != nil { - return err - } else { - io.Copy(wField, file) - } - multipartBody = io.MultiReader(multipartBody, boundary) - compression := Bzip2 - // Create a FormFile multipart for the context if needed - if contextPath != "" { + if cmd.Arg(0) == "-" { + file = os.Stdin + } else { + // Send Dockerfile from arg/Dockerfile (deprecate later) + if f, err := os.Open(path.Join(cmd.Arg(0), "Dockerfile")); err != nil { + return err + } else { + 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? - context, err := Tar(contextPath, compression) + context, err := Tar(cmd.Arg(0), compression) if err != nil { return err } // NOTE: Do this in case '.' or '..' is input - absPath, err := filepath.Abs(contextPath) + absPath, err := filepath.Abs(cmd.Arg(0)) if err != nil { return err } @@ -194,9 +181,15 @@ func (cli *DockerCli) CmdBuild(args ...string) error { // FIXME: Find a way to have a progressbar for the upload too io.Copy(wField, utils.ProgressReader(ioutil.NopCloser(context), -1, os.Stdout, "Caching Context %v/%v (%v)\r", false)) } - multipartBody = io.MultiReader(multipartBody, boundary) } + // Create a FormFile multipart for the Dockerfile + if wField, err := w.CreateFormFile("Dockerfile", "Dockerfile"); err != nil { + return err + } else { + io.Copy(wField, file) + } + multipartBody = io.MultiReader(multipartBody, boundary) // Send the multipart request with correct content-type req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s", cli.host, cli.port, "/build"), multipartBody) From 9a394041270d2a8ba648f215dacc186473140552 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Wed, 29 May 2013 18:55:00 -0700 Subject: [PATCH 23/79] Fix issue with mkdir within docker build --- buildfile.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/buildfile.go b/buildfile.go index 805ebb4fbb..b4c96e36d5 100644 --- a/buildfile.go +++ b/buildfile.go @@ -221,15 +221,15 @@ func (b *buildFile) CmdAdd(args string) error { origPath := path.Join(b.context, orig) destPath := path.Join(container.RootfsPath(), dest) - if err := os.MkdirAll(path.Dir(destPath), 0700); err != nil { - return err - } - fi, err := os.Stat(origPath) if err != nil { return err } if fi.IsDir() { + if err := os.MkdirAll(destPath, 0700); err != nil { + return err + } + files, err := ioutil.ReadDir(path.Join(b.context, orig)) if err != nil { return err @@ -240,6 +240,9 @@ func (b *buildFile) CmdAdd(args string) error { } } } else { + if err := os.MkdirAll(path.Dir(destPath), 0700); err != nil { + return err + } if err := utils.CopyDirectory(origPath, destPath); err != nil { return err } From 97247c5c733db355f7261ddad5223a00c33c635e Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Wed, 29 May 2013 21:57:36 -0700 Subject: [PATCH 24/79] 'docker build': remove INSERT command (should add support for remote sources in ADD instead) --- buildfile.go | 39 --------------------------------------- 1 file changed, 39 deletions(-) diff --git a/buildfile.go b/buildfile.go index b4c96e36d5..a4ef2de0a9 100644 --- a/buildfile.go +++ b/buildfile.go @@ -152,45 +152,6 @@ func (b *buildFile) CmdExpose(args string) error { return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports)) } -func (b *buildFile) CmdInsert(args string) error { - if b.image == "" { - return fmt.Errorf("Please provide a source image with `from` prior to insert") - } - tmp := strings.SplitN(args, " ", 2) - if len(tmp) != 2 { - return fmt.Errorf("Invalid INSERT format") - } - sourceUrl := strings.Trim(tmp[0], " ") - destPath := strings.Trim(tmp[1], " ") - - file, err := utils.Download(sourceUrl, b.out) - if err != nil { - return err - } - defer file.Body.Close() - - cmd := b.config.Cmd - b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) INSERT %s in %s", sourceUrl, destPath)} - cid, err := b.run() - if err != nil { - return err - } - - container := b.runtime.Get(cid) - if container == nil { - return fmt.Errorf("An error occured while creating the container") - } - - if err := container.Inject(file.Body, destPath); err != nil { - return err - } - if err := b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)); err != nil { - return err - } - b.config.Cmd = cmd - return nil -} - func (b *buildFile) CmdAdd(args string) error { if b.context == "" { return fmt.Errorf("No context given. Impossible to use ADD") From 531b30119ab5422f9f34ebf3be1a6b6578ded9f1 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 30 May 2013 11:37:58 -0700 Subject: [PATCH 25/79] Remove special case for 'teams' from registry api --- docs/sources/api/registry_api.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/sources/api/registry_api.rst b/docs/sources/api/registry_api.rst index 7034d90e27..bb8a16652d 100644 --- a/docs/sources/api/registry_api.rst +++ b/docs/sources/api/registry_api.rst @@ -246,7 +246,6 @@ The Index has two main purposes (along with its fancy social features): - Resolve short names (to avoid passing absolute URLs all the time) - username/projectname -> \https://registry.docker.io/users//repositories// - - team/projectname -> \https://registry.docker.io/team//repositories// - Authenticate a user as a repos owner (for a central referenced repository) 3.1 Without an Index From 56431d3130f8a48cfb708509cbe39682f7fe841c Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 30 May 2013 12:08:21 -0700 Subject: [PATCH 26/79] Add -t to docker build in order to tag resulting image --- api.go | 11 ++++++++++- commands.go | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/api.go b/api.go index 3c440d7331..621d9c82e1 100644 --- a/api.go +++ b/api.go @@ -650,6 +650,13 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ if err := r.ParseMultipartForm(4096); err != nil { return err } + remote := r.FormValue("t") + tag := "" + if strings.Contains(remote, ":") { + remoteParts := strings.Split(remote, ":") + tag = remoteParts[1] + remote = remoteParts[0] + } dockerfile, _, err := r.FormFile("Dockerfile") if err != nil { @@ -664,8 +671,10 @@ func postBuild(srv *Server, version float64, w http.ResponseWriter, r *http.Requ } b := NewBuildFile(srv, utils.NewWriteFlusher(w)) - if _, err := b.Build(dockerfile, context); err != nil { + if id, err := b.Build(dockerfile, context); err != nil { fmt.Fprintf(w, "Error build: %s\n", err) + } else if remote != "" { + srv.runtime.repositories.Set(remote, tag, id, false) } return nil } diff --git a/commands.go b/commands.go index 67b8e917f5..c24a48f5a0 100644 --- a/commands.go +++ b/commands.go @@ -132,6 +132,7 @@ func (cli *DockerCli) CmdInsert(args ...string) error { func (cli *DockerCli) CmdBuild(args ...string) error { cmd := Subcmd("build", "PATH | -", "Build a new container image from the source code at PATH") + tag := cmd.String("t", "", "Tag to be applied to the resulting image") if err := cmd.Parse(args); err != nil { return nil } @@ -191,8 +192,10 @@ func (cli *DockerCli) CmdBuild(args ...string) error { } multipartBody = io.MultiReader(multipartBody, boundary) + v := &url.Values{} + v.Set("t", *tag) // Send the multipart request with correct content-type - req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s", cli.host, cli.port, "/build"), multipartBody) + req, err := http.NewRequest("POST", fmt.Sprintf("http://%s:%d%s?%s", cli.host, cli.port, "/build", v.Encode()), multipartBody) if err != nil { return err } From a4e6025cc1103d1ad9c86fa5d75f832526d2a7b8 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 30 May 2013 12:10:54 -0700 Subject: [PATCH 27/79] Deprecate INSERT and COPY --- buildfile.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/buildfile.go b/buildfile.go index a4ef2de0a9..cf8f3e8e56 100644 --- a/buildfile.go +++ b/buildfile.go @@ -152,6 +152,14 @@ func (b *buildFile) CmdExpose(args string) error { return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports)) } +func (b *buildFile) CmdInsert(args string) error { + return fmt.Errorf("INSERT has been deprecated. Please use ADD instead") +} + +func (b *buildFile) CmdCopy(args string) error { + return fmt.Errorf("COPY has been deprecated. Please use ADD instead") +} + func (b *buildFile) CmdAdd(args string) error { if b.context == "" { return fmt.Errorf("No context given. Impossible to use ADD") From 6d2e3d2ec0dedc6c1429e87800e9f3d7e4ada095 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 30 May 2013 12:21:57 -0700 Subject: [PATCH 28/79] Fix issue with CMD instruction within docker build --- buildfile.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/buildfile.go b/buildfile.go index cf8f3e8e56..3081367719 100644 --- a/buildfile.go +++ b/buildfile.go @@ -143,7 +143,11 @@ func (b *buildFile) CmdCmd(args string) error { utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err) cmd = []string{"/bin/sh", "-c", args} } - return b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)) + if err := b.commit("", cmd, fmt.Sprintf("CMD %v", cmd)); err != nil { + return err + } + b.config.Cmd = cmd + return nil } func (b *buildFile) CmdExpose(args string) error { @@ -216,7 +220,11 @@ func (b *buildFile) CmdAdd(args string) error { return err } } - return b.commit(cid, cmd, fmt.Sprintf("ADD %s in %s", orig, dest)) + if err := b.commit(cid, cmd, fmt.Sprintf("ADD %s in %s", orig, dest)); err != nil { + return err + } + b.config.Cmd = cmd + return nil } func (b *buildFile) run() (string, error) { From 43f369ea0ca5d07a1e3b6d04864ad204c3c65357 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 30 May 2013 12:28:24 -0700 Subject: [PATCH 29/79] Organize the project infrastructure: servers, dns, email etc. --- hack/infrastructure/MAINTAINERS | 2 ++ hack/infrastructure/README.md | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 hack/infrastructure/MAINTAINERS create mode 100644 hack/infrastructure/README.md diff --git a/hack/infrastructure/MAINTAINERS b/hack/infrastructure/MAINTAINERS new file mode 100644 index 0000000000..490b0c1ea2 --- /dev/null +++ b/hack/infrastructure/MAINTAINERS @@ -0,0 +1,2 @@ +Ken Cochrane +Jerome Petazzoni diff --git a/hack/infrastructure/README.md b/hack/infrastructure/README.md new file mode 100644 index 0000000000..126792a6b0 --- /dev/null +++ b/hack/infrastructure/README.md @@ -0,0 +1,5 @@ +# Docker project infrastructure + +This directory holds all information about the technical infrastructure of the docker project; servers, dns, email, and all the corresponding tools and configuration. + +Obviously credentials should not be stored in this repo, but how to obtain and use them should be documented here. From 28d5b2c15acc6e088a0abd2099a00ba1180beb3e Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Thu, 30 May 2013 12:35:19 -0700 Subject: [PATCH 30/79] Update docker build docs --- commands.go | 4 ++-- docs/sources/commandline/command/build.rst | 21 +++++---------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/commands.go b/commands.go index c24a48f5a0..14491d31a1 100644 --- a/commands.go +++ b/commands.go @@ -131,8 +131,8 @@ func (cli *DockerCli) CmdInsert(args ...string) error { } func (cli *DockerCli) CmdBuild(args ...string) error { - cmd := Subcmd("build", "PATH | -", "Build a new container image from the source code at PATH") - tag := cmd.String("t", "", "Tag to be applied to the resulting image") + cmd := Subcmd("build", "[OPTIONS] PATH | -", "Build a new container image from the source code at PATH") + tag := cmd.String("t", "", "Tag to be applied to the resulting image in case of success") if err := cmd.Parse(args); err != nil { return nil } diff --git a/docs/sources/commandline/command/build.rst b/docs/sources/commandline/command/build.rst index f7df8cbbc3..81120b22d2 100644 --- a/docs/sources/commandline/command/build.rst +++ b/docs/sources/commandline/command/build.rst @@ -8,32 +8,21 @@ :: - Usage: docker build [CONTEXT|-] - Build a new image from a Dockerfile + Usage: docker build [OPTIONS] PATH | - + Build a new container image from the source code at PATH + -t="": Tag to be applied to the resulting image in case of success. Examples -------- .. code-block:: bash - docker build + docker build . -This will take the local Dockerfile without context +This will take the local Dockerfile .. code-block:: bash docker build - This will read a Dockerfile form Stdin without context - -.. code-block:: bash - - docker build . - -This will take the local Dockerfile and set the current directory as context - -.. code-block:: bash - - docker build - . - -This will read a Dockerfile from Stdin and set the current directory as context From c903a6baf83b4aaa51d7198643e0eef9211c99ed Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 30 May 2013 15:52:09 -0700 Subject: [PATCH 31/79] * Builder: keep temporary images after a build fails, to allow caching --- buildfile.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/buildfile.go b/buildfile.go index 3081367719..81aea513db 100644 --- a/buildfile.go +++ b/buildfile.go @@ -347,10 +347,6 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { fmt.Fprintf(b.out, "===> %v\n", b.image) } if b.image != "" { - // The build is successful, keep the temporary containers and images - for i := range b.tmpImages { - delete(b.tmpImages, i) - } fmt.Fprintf(b.out, "Build successful.\n===> %s\n", b.image) return b.image, nil } From caaea2e08f85438b7a6bee006e803f1c4351c445 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 30 May 2013 16:24:26 -0700 Subject: [PATCH 32/79] * Build: never remove temporary images and containers --- buildfile.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/buildfile.go b/buildfile.go index 81aea513db..d9a4b5eff6 100644 --- a/buildfile.go +++ b/buildfile.go @@ -298,8 +298,6 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { } func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { - defer b.clearTmp(b.tmpContainers, b.tmpImages) - if context != nil { name, err := ioutil.TempDir("/tmp", "docker-build") if err != nil { @@ -350,9 +348,6 @@ func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) { fmt.Fprintf(b.out, "Build successful.\n===> %s\n", b.image) return b.image, nil } - for i := range b.tmpContainers { - delete(b.tmpContainers, i) - } return "", fmt.Errorf("An error occured during the build\n") } From 8d73740343778651c09160cde9661f5f387b36f4 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Thu, 30 May 2013 17:27:45 -0700 Subject: [PATCH 33/79] Bumped version to 0.3.4 --- CHANGELOG.md | 9 +++++++++ commands.go | 2 +- packaging/debian/changelog | 11 +++++++++++ packaging/ubuntu/changelog | 12 ++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3502d23a..a8464b5345 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 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. + + Runtime: interactive TTYs correctly handle window resize + * Runtime: fix how configuration is merged between layers + + Remote API: split stdout and stderr on 'docker run' + + Remote API: optionally listen on a different IP and port (use at your own risk) + * Documentation: improved install instructions. + ## 0.3.3 (2013-05-23) - Registry: Fix push regression - Various bugfixes diff --git a/commands.go b/commands.go index 38deb1a561..0e8d0b48f2 100644 --- a/commands.go +++ b/commands.go @@ -28,7 +28,7 @@ import ( "unicode" ) -const VERSION = "0.3.3" +const VERSION = "0.3.4" var ( GIT_COMMIT string diff --git a/packaging/debian/changelog b/packaging/debian/changelog index c7a34d4869..55102dd2ac 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -1,3 +1,14 @@ +lxc-docker (0.3.4-1) UNRELEASED; urgency=low + - 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. + - Runtime: interactive TTYs correctly handle window resize + - Runtime: fix how configuration is merged between layers + - Remote API: split stdout and stderr on 'docker run' + - Remote API: optionally listen on a different IP and port (use at your own risk) + - Documentation: improved install instructions. + + -- dotCloud Thu, 30 May 2013 00:00:00 -0700 + lxc-docker (0.3.2-1) UNRELEASED; urgency=low - Runtime: Store the actual archive on commit - Registry: Improve the checksum process diff --git a/packaging/ubuntu/changelog b/packaging/ubuntu/changelog index c8a8c1689b..10151ed483 100644 --- a/packaging/ubuntu/changelog +++ b/packaging/ubuntu/changelog @@ -1,3 +1,15 @@ +lxc-docker (0.3.4-1) precise; urgency=low + - 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. + - Runtime: interactive TTYs correctly handle window resize + - Runtime: fix how configuration is merged between layers + - Remote API: split stdout and stderr on 'docker run' + - Remote API: optionally listen on a different IP and port (use at your own risk) + - Documentation: improved install instructions. + + -- dotCloud Thu, 30 May 2013 00:00:00 -0700 + + lxc-docker (0.3.3-1) precise; urgency=low - Registry: Fix push regression - Various bugfixes From 1040225e36c6b235d5f82e44685b2f942be68965 Mon Sep 17 00:00:00 2001 From: Daniel Mizyrycki Date: Fri, 31 May 2013 00:59:18 -0700 Subject: [PATCH 34/79] Packaging: Ensure dockerbuilder can build docker PPA --- hack/dockerbuilder/Dockerfile | 20 ++++++++++++++------ hack/dockerbuilder/dockerbuilder | 3 ++- hack/dockerbuilder/fake_initctl | 3 --- 3 files changed, 16 insertions(+), 10 deletions(-) delete mode 100755 hack/dockerbuilder/fake_initctl diff --git a/hack/dockerbuilder/Dockerfile b/hack/dockerbuilder/Dockerfile index 8a7382e885..5f9e9c35ab 100644 --- a/hack/dockerbuilder/Dockerfile +++ b/hack/dockerbuilder/Dockerfile @@ -1,23 +1,31 @@ # This will build a container capable of producing an official binary build of docker and # uploading it to S3 +from ubuntu:12.04 maintainer Solomon Hykes -from ubuntu:12.10 +# Workaround the upstart issue +run dpkg-divert --local --rename --add /sbin/initctl +run ln -s /bin/true /sbin/initctl +# Enable universe and gophers PPA +run DEBIAN_FRONTEND=noninteractive apt-get install -y -q python-software-properties +run add-apt-repository "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) universe" +run add-apt-repository -y ppa:gophers/go/ubuntu run apt-get update +# Packages required to checkout, build and upload docker run DEBIAN_FRONTEND=noninteractive apt-get install -y -q s3cmd run DEBIAN_FRONTEND=noninteractive apt-get install -y -q curl -# Packages required to checkout and build docker run curl -s -o /go.tar.gz https://go.googlecode.com/files/go1.1.linux-amd64.tar.gz run tar -C /usr/local -xzf /go.tar.gz -run echo "export PATH=$PATH:/usr/local/go/bin" > /.bashrc -run echo "export PATH=$PATH:/usr/local/go/bin" > /.bash_profile +run echo "export PATH=/usr/local/go/bin:$PATH" > /.bashrc +run echo "export PATH=/usr/local/go/bin:$PATH" > /.bash_profile run DEBIAN_FRONTEND=noninteractive apt-get install -y -q git run DEBIAN_FRONTEND=noninteractive apt-get install -y -q build-essential # Packages required to build an ubuntu package +run DEBIAN_FRONTEND=noninteractive apt-get install -y -q golang-stable run DEBIAN_FRONTEND=noninteractive apt-get install -y -q debhelper run DEBIAN_FRONTEND=noninteractive apt-get install -y -q autotools-dev -copy fake_initctl /usr/local/bin/initctl run apt-get install -y -q devscripts -add . /src +# Copy dockerbuilder files into the container +add . /src run cp /src/dockerbuilder /usr/local/bin/ && chmod +x /usr/local/bin/dockerbuilder run cp /src/s3cfg /.s3cfg cmd ["dockerbuilder"] diff --git a/hack/dockerbuilder/dockerbuilder b/hack/dockerbuilder/dockerbuilder index 4287e0b336..d2e4396550 100644 --- a/hack/dockerbuilder/dockerbuilder +++ b/hack/dockerbuilder/dockerbuilder @@ -2,7 +2,7 @@ set -x set -e -export PATH=$PATH:/usr/local/go/bin +export PATH=/usr/local/go/bin:$PATH PACKAGE=github.com/dotcloud/docker @@ -36,5 +36,6 @@ else fi if [ -z "$NO_UBUNTU" ]; then + export PATH=`echo $PATH | sed 's#/usr/local/go/bin:##g'` (cd packaging/ubuntu && make ubuntu) fi diff --git a/hack/dockerbuilder/fake_initctl b/hack/dockerbuilder/fake_initctl deleted file mode 100755 index 14c46c8e94..0000000000 --- a/hack/dockerbuilder/fake_initctl +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -echo Whatever you say, man From 2baea2487936c3d385671d25ab3ef1b09f9007cc Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 31 May 2013 14:40:09 +0000 Subject: [PATCH 35/79] add -t parameter in the doc --- docs/sources/api/docker_remote_api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index bd87dc7a03..66e8348e72 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -826,6 +826,7 @@ Build an image from Dockerfile via stdin {{ STREAM }} + :query t: tag to be applied to the resulting image in case of success :statuscode 200: no error :statuscode 500: server error From 468e4c4b565d25b03c68ce2ab31f9a52f7b3398a Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Fri, 31 May 2013 15:34:23 +0000 Subject: [PATCH 36/79] returns an error if the container we want to attach is not running --- api.go | 2 ++ docs/sources/api/docker_remote_api.rst | 1 + server.go | 4 +++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/api.go b/api.go index 621d9c82e1..e6ac49ad28 100644 --- a/api.go +++ b/api.go @@ -45,6 +45,8 @@ func httpError(w http.ResponseWriter, err error) { http.Error(w, err.Error(), http.StatusNotFound) } else if strings.HasPrefix(err.Error(), "Bad parameter") { http.Error(w, err.Error(), http.StatusBadRequest) + } else if strings.HasPrefix(err.Error(), "Impossible") { + http.Error(w, err.Error(), http.StatusNotAcceptable) } else { http.Error(w, err.Error(), http.StatusInternalServerError) } diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index bd87dc7a03..98b0005cda 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -132,6 +132,7 @@ Create a container :jsonparam config: the container's configuration :statuscode 201: no error :statuscode 404: no such container + :statuscode 406: impossible to attach (container not running) :statuscode 500: server error diff --git a/server.go b/server.go index 0440b0a8a4..90ec79986c 100644 --- a/server.go +++ b/server.go @@ -790,7 +790,6 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std if container == nil { return fmt.Errorf("No such container: %s", name) } - //logs if logs { if stdout { @@ -816,6 +815,9 @@ func (srv *Server) ContainerAttach(name string, logs, stream, stdin, stdout, std if container.State.Ghost { return fmt.Errorf("Impossible to attach to a ghost container") } + if !container.State.Running { + return fmt.Errorf("Impossible to attach to a stopped container, start it first") + } var ( cStdin io.ReadCloser From fd0c501e6d65b665cba87f3449e02a722d90e6b1 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Fri, 31 May 2013 12:19:49 -0700 Subject: [PATCH 37/79] =?UTF-8?q?Fix=20minor=20documentation=20error=20in?= =?UTF-8?q?=20=E2=80=98Running=20Redis=20Service=E2=80=99=20example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sources/examples/running_redis_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/examples/running_redis_service.rst b/docs/sources/examples/running_redis_service.rst index 018b061707..4b5d161e61 100644 --- a/docs/sources/examples/running_redis_service.rst +++ b/docs/sources/examples/running_redis_service.rst @@ -34,7 +34,7 @@ Snapshot the installation .. code-block:: bash - docker ps -a # grab the container id (this will be the last one in the list) + docker ps -a # grab the container id (this will be the first one in the list) docker commit /redis Run the service From 766a2db0d94d0f7cd8bdb71762476893a4df4cc1 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Fri, 31 May 2013 12:19:57 -0700 Subject: [PATCH 38/79] Add Daniel Gasienica to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index fdddedde15..1599a1d0e1 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,6 +15,7 @@ Brian McCallister Bruno Bigras Caleb Spare Charles Hooper +Daniel Gasienica Daniel Mizyrycki Daniel Robinson Daniel Von Fange From 1dae7a25b919dc70798cbab8107809690212cd69 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 31 May 2013 15:53:57 -0700 Subject: [PATCH 39/79] Improve the docker version and docker info commands --- api_params.go | 23 +++++++++++------------ commands.go | 34 +++++++++++++++++++++------------- server.go | 26 ++++++++++++++------------ 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/api_params.go b/api_params.go index 1a24ab2875..e18238b735 100644 --- a/api_params.go +++ b/api_params.go @@ -3,7 +3,7 @@ package docker type ApiHistory struct { Id string Created int64 - CreatedBy string + CreatedBy string `json:",omitempty"` } type ApiImages struct { @@ -14,13 +14,13 @@ type ApiImages struct { } type ApiInfo struct { - Containers int - Version string - Images int 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 ApiContainers struct { @@ -43,7 +43,7 @@ type ApiId struct { type ApiRun struct { Id string - Warnings []string + Warnings []string `json:",omitempty"` } type ApiPort struct { @@ -51,10 +51,9 @@ type ApiPort struct { } type ApiVersion struct { - Version string - GitCommit string - MemoryLimit bool - SwapLimit bool + Version string + GitCommit string `json:",omitempty"` + GoVersion string `json:",omitempty"` } type ApiWait struct { diff --git a/commands.go b/commands.go index 6109aebb13..9765b85cab 100644 --- a/commands.go +++ b/commands.go @@ -391,15 +391,14 @@ func (cli *DockerCli) CmdVersion(args ...string) error { 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,14 +419,23 @@ func (cli *DockerCli) CmdInfo(args ...string) error { } var out ApiInfo - err = json.Unmarshal(body, &out) - if err != nil { + 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 } diff --git a/server.go b/server.go index 90ec79986c..088353c3f7 100644 --- a/server.go +++ b/server.go @@ -17,7 +17,11 @@ import ( ) func (srv *Server) DockerVersion() ApiVersion { - return ApiVersion{VERSION, GIT_COMMIT, srv.runtime.capabilities.MemoryLimit, srv.runtime.capabilities.SwapLimit} + return ApiVersion{ + Version: VERSION, + GitCommit: GIT_COMMIT, + GoVersion: runtime.Version(), + } } func (srv *Server) ContainerKill(name string) error { @@ -187,7 +191,7 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { return outs, nil } -func (srv *Server) DockerInfo() ApiInfo { +func (srv *Server) DockerInfo() *ApiInfo { images, _ := srv.runtime.graph.All() var imgcount int if images == nil { @@ -195,17 +199,15 @@ func (srv *Server) DockerInfo() ApiInfo { } else { imgcount = len(images) } - var out ApiInfo - out.Containers = len(srv.runtime.List()) - out.Version = VERSION - out.Images = imgcount - out.GoVersion = runtime.Version() - if os.Getenv("DEBUG") != "" { - out.Debug = true - out.NFd = utils.GetTotalUsedFds() - out.NGoroutines = runtime.NumGoroutine() + return &ApiInfo{ + Containers: len(srv.runtime.List()), + Images: imgcount, + MemoryLimit: srv.runtime.capabilities.MemoryLimit, + SwapLimit: srv.runtime.capabilities.SwapLimit, + Debug: os.Getenv("DEBUG") != "", + NFd: utils.GetTotalUsedFds(), + NGoroutines: runtime.NumGoroutine(), } - return out } func (srv *Server) ImageHistory(name string) ([]ApiHistory, error) { From f41d2ec4d91f2fa1dc479d8bac32113fbb7e987e Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Fri, 31 May 2013 15:56:30 -0700 Subject: [PATCH 40/79] Update api docs --- docs/sources/api/docker_remote_api.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index 5056a62a19..e350b9746c 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -914,10 +914,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 @@ -943,12 +945,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 From 561ceac55d5821a00258934cf9dc215278e3ecfd Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Fri, 31 May 2013 22:25:48 -0700 Subject: [PATCH 41/79] * Runtime: pass a guaranteed environment to bsdtar for predictable behavior without depending on the underlying host configuration. --- archive.go | 3 +++ packaging/ubuntu/docker.upstart | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/archive.go b/archive.go index 4120a52c1d..06466627a1 100644 --- a/archive.go +++ b/archive.go @@ -54,6 +54,9 @@ func Tar(path string, compression Compression) (io.Reader, error) { func Untar(archive io.Reader, path string) error { cmd := exec.Command("bsdtar", "-f", "-", "-C", path, "-x") cmd.Stdin = archive + // Hardcode locale environment for predictable outcome regardless of host configuration. + // (see https://github.com/dotcloud/docker/issues/355) + cmd.Env = []string{"LANG=en_US.utf-8", "LC_ALL=en_US.utf-8"} output, err := cmd.CombinedOutput() if err != nil { return fmt.Errorf("%s: %s", err, output) diff --git a/packaging/ubuntu/docker.upstart b/packaging/ubuntu/docker.upstart index 07e7e8a890..2bd5565ee7 100644 --- a/packaging/ubuntu/docker.upstart +++ b/packaging/ubuntu/docker.upstart @@ -5,6 +5,5 @@ stop on starting rc RUNLEVEL=[016] respawn script - # FIXME: docker should not depend on the system having en_US.UTF-8 - LC_ALL='en_US.UTF-8' /usr/bin/docker -d + /usr/bin/docker -d end script From 64f346779fbe4ba9587ec65eedd0e8373f7e29c0 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Sat, 1 Jun 2013 15:51:45 -0700 Subject: [PATCH 42/79] Remove cgo from term --- term/term.go | 12 +++++------ term/termios_linux.go | 50 +++++++++++-------------------------------- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/term/term.go b/term/term.go index 290bf174ad..ab90a3ef73 100644 --- a/term/term.go +++ b/term/term.go @@ -8,13 +8,13 @@ import ( ) type Termios struct { - Iflag uintptr - Oflag uintptr - Cflag uintptr - Lflag uintptr + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 Cc [20]byte - Ispeed uintptr - Ospeed uintptr + Ispeed uint32 + Ospeed uint32 } const ( diff --git a/term/termios_linux.go b/term/termios_linux.go index 92f21edde2..31a10a307c 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -5,26 +5,6 @@ import ( "unsafe" ) -// #include -// #include -/* -void MakeRaw(int fd) { - struct termios t; - - // FIXME: Handle errors? - ioctl(fd, TCGETS, &t); - - t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - t.c_oflag &= ~OPOST; - t.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); - t.c_cflag &= ~(CSIZE | PARENB); - t.c_cflag |= CS8; - - ioctl(fd, TCSETS, &t); -} -*/ -import "C" - const ( getTermios = syscall.TCGETS setTermios = syscall.TCSETS @@ -35,24 +15,20 @@ const ( // restored. func MakeRaw(fd int) (*State, error) { var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { + return nil, err + } + + newState := oldState.termios + + newState.Iflag &^= (syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON) + newState.Oflag &^= syscall.OPOST + newState.Lflag &^= (syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN) + newState.Cflag &^= (syscall.CSIZE | syscall.PARENB) + newState.Cflag |= syscall.CS8 + + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err } - C.MakeRaw(C.int(fd)) return &oldState, nil - - // FIXME: post on goland issues this: very same as the C function bug non-working - - // newState := oldState.termios - - // newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON) - // newState.Oflag &^= OPOST - // newState.Lflag &^= (ECHO | syscall.ECHONL | ICANON | ISIG | IEXTEN) - // newState.Cflag &^= (CSIZE | syscall.PARENB) - // newState.Cflag |= CS8 - - // if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TCSETS, uintptr(unsafe.Pointer(&newState))); err != 0 { - // return nil, err - // } - // return &oldState, nil } From 31eb01ae8aac22a4d768418d3cc4da6f903a8694 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Sat, 1 Jun 2013 15:55:05 -0700 Subject: [PATCH 43/79] Use uintptr instead of int for Fd --- commands.go | 4 ++-- term/term.go | 14 +++++++------- term/termios_linux.go | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/commands.go b/commands.go index 7dd835856f..977ff12839 100644 --- a/commands.go +++ b/commands.go @@ -1414,7 +1414,7 @@ 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 in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" { if oldState, err := term.SetRawTerminal(); err != nil { return err } else { @@ -1433,7 +1433,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/term/term.go b/term/term.go index ab90a3ef73..4e29361533 100644 --- a/term/term.go +++ b/term/term.go @@ -128,21 +128,21 @@ func SetWinsize(fd uintptr, ws *Winsize) error { } // IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd int) bool { +func IsTerminal(fd uintptr) bool { var termios Termios - _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) + _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) return err == 0 } // Restore restores the terminal connected to the given file descriptor to a // previous state. -func Restore(fd int, state *State) error { - _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) +func Restore(fd uintptr, state *State) error { + _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) return err } func SetRawTerminal() (*State, error) { - oldState, err := MakeRaw(int(os.Stdin.Fd())) + oldState, err := MakeRaw(os.Stdin.Fd()) if err != nil { return nil, err } @@ -150,12 +150,12 @@ func SetRawTerminal() (*State, error) { signal.Notify(c, os.Interrupt) go func() { _ = <-c - Restore(int(os.Stdin.Fd()), oldState) + Restore(os.Stdin.Fd(), oldState) os.Exit(0) }() return oldState, err } func RestoreTerminal(state *State) { - Restore(int(os.Stdin.Fd()), state) + Restore(os.Stdin.Fd(), state) } diff --git a/term/termios_linux.go b/term/termios_linux.go index 31a10a307c..7877cb89f8 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -13,9 +13,9 @@ const ( // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. -func MakeRaw(fd int) (*State, error) { +func MakeRaw(fd uintptr) (*State, error) { var oldState State - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { return nil, err } @@ -27,7 +27,7 @@ func MakeRaw(fd int) (*State, error) { newState.Cflag &^= (syscall.CSIZE | syscall.PARENB) newState.Cflag |= syscall.CS8 - if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err } return &oldState, nil From 3cc0963ad16a5abd67aeba22cefac34a40ac70ef Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Sat, 1 Jun 2013 15:55:52 -0700 Subject: [PATCH 44/79] Remove unused constants --- term/term.go | 88 ---------------------------------------------------- 1 file changed, 88 deletions(-) diff --git a/term/term.go b/term/term.go index 4e29361533..1f3e9d36bb 100644 --- a/term/term.go +++ b/term/term.go @@ -17,94 +17,6 @@ type Termios struct { Ospeed uint32 } -const ( - // Input flags - inpck = 0x010 - istrip = 0x020 - icrnl = 0x100 - ixon = 0x200 - - // Output flags - opost = 0x1 - - // Control flags - cs8 = 0x300 - - // Local flags - icanon = 0x100 - iexten = 0x400 -) - -const ( - HUPCL = 0x4000 - ICANON = 0x100 - ICRNL = 0x100 - IEXTEN = 0x400 - BRKINT = 0x2 - CFLUSH = 0xf - CLOCAL = 0x8000 - CREAD = 0x800 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - NOFLSH = 0x80000000 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - RENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - ECHO = 0x00000008 - - PENDIN = 0x20000000 -) - type State struct { termios Termios } From a70dd65964340b5c4ccedf497a2605b13e7ac8a8 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Sat, 1 Jun 2013 16:19:50 -0700 Subject: [PATCH 45/79] Move Termios struct to os specific file --- term/term.go | 10 ---------- term/termios_darwin.go | 32 +++++++++++++++++++++++++++----- term/termios_linux.go | 10 ++++++++++ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/term/term.go b/term/term.go index 1f3e9d36bb..0cc91ea1b6 100644 --- a/term/term.go +++ b/term/term.go @@ -7,16 +7,6 @@ import ( "unsafe" ) -type Termios struct { - Iflag uint32 - Oflag uint32 - Cflag uint32 - Lflag uint32 - Cc [20]byte - Ispeed uint32 - Ospeed uint32 -} - type State struct { termios Termios } diff --git a/term/termios_darwin.go b/term/termios_darwin.go index 7df54e7828..ac18aab692 100644 --- a/term/termios_darwin.go +++ b/term/termios_darwin.go @@ -8,23 +8,45 @@ import ( const ( getTermios = syscall.TIOCGETA setTermios = syscall.TIOCSETA + + ECHO = 0x00000008 + ONLCR = 0x2 + ISTRIP = 0x20 + INLCR = 0x40 + ISIG = 0x80 + IGNCR = 0x80 + ICANON = 0x100 + ICRNL = 0x100 + IXOFF = 0x400 + IXON = 0x200 ) +type Termios struct { + Iflag uint64 + Oflag uint64 + Cflag uint64 + Lflag uint64 + Cc [20]byte + Ispeed uint64 + Ospeed uint64 +} + // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. -func MakeRaw(fd int) (*State, error) { +func MakeRaw(fd uintptr) (*State, error) { var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { return nil, err } newState := oldState.termios - newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF + newState.Iflag &^= (ISTRIP | INLCR | IGNCR | IXON | IXOFF) newState.Iflag |= ICRNL newState.Oflag |= ONLCR - newState.Lflag &^= ECHO | ICANON | ISIG - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + newState.Lflag &^= (ECHO | ICANON | ISIG) + + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err } diff --git a/term/termios_linux.go b/term/termios_linux.go index 7877cb89f8..4a717c84a7 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -10,6 +10,16 @@ const ( setTermios = syscall.TCSETS ) +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]byte + Ispeed uint32 + Ospeed uint32 +} + // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. From 7f65bf508e5930df48e3e3de2ed9a5a62a66446c Mon Sep 17 00:00:00 2001 From: Jon Wedaman Date: Sat, 1 Jun 2013 21:48:32 -0400 Subject: [PATCH 46/79] Spelling correction in docs --- docs/website/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/website/index.html b/docs/website/index.html index d441ed8d78..bc3e2d0271 100644 --- a/docs/website/index.html +++ b/docs/website/index.html @@ -270,7 +270,7 @@
  • Filesystem isolation: each process container runs in a completely separate root filesystem.
  • Resource isolation: system resources like cpu and memory can be allocated differently to each process container, using cgroups.
  • Network isolation: each process container runs in its own network namespace, with a virtual interface and IP address of its own.
  • -
  • Copy-on-write: root filesystems are created using copy-on-write, which makes deployment extremeley fast, memory-cheap and disk-cheap.
  • +
  • Copy-on-write: root filesystems are created using copy-on-write, which makes deployment extremely fast, memory-cheap and disk-cheap.
  • Logging: the standard streams (stdout/stderr/stdin) of each process container is collected and logged for real-time or batch retrieval.
  • Change management: changes to a container's filesystem can be committed into a new image and re-used to create more containers. No templating or manual configuration required.
  • Interactive shell: docker can allocate a pseudo-tty and attach to the standard input of any container, for example to run a throwaway interactive shell.
  • From b4df0b17afef027e88f0536cbfc9518e04f62eec Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:25:51 -0700 Subject: [PATCH 47/79] Add `make server` command to preview docs --- docs/Makefile | 4 ++++ docs/README.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index 26168b6f38..dcbf111c29 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -6,6 +6,7 @@ SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build +PYTHON = python # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 @@ -38,6 +39,7 @@ help: # @echo " linkcheck to check all external links for integrity" # @echo " doctest to run all doctests embedded in the documentation (if enabled)" @echo " docs to build the docs and copy the static files to the outputdir" + @echo " server to serve the docs in your browser under \`http://localhost:8000\`" @echo " publish to publish the app to dotcloud" clean: @@ -49,6 +51,8 @@ docs: @echo @echo "Build finished. The documentation pages are now in $(BUILDDIR)/html." +server: + @cd $(BUILDDIR)/html; $(PYTHON) -m SimpleHTTPServer 8000 site: cp -r website $(BUILDDIR)/ diff --git a/docs/README.md b/docs/README.md index e1ca45b085..ef24c3fb1d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,7 +23,7 @@ Usage * change the .rst files with your favorite editor to your liking * run *make docs* to clean up old files and generate new ones * your static website can now be found in the _build dir -* to preview what you have generated, cd into _build/html and then run 'python -m SimpleHTTPServer 8000' +* to preview what you have generated run `make server` and open in your favorite browser. Working using github's file editor ---------------------------------- From 3ca9c11110ff5068fd453a3e8aa0b39ee26d363c Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:26:18 -0700 Subject: [PATCH 48/79] Add Mac OS X instructions for doc tools --- docs/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index ef24c3fb1d..54588e995d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,8 +14,10 @@ Installation ------------ * Work in your own fork of the code, we accept pull requests. -* Install sphinx: ``pip install sphinx`` -* Install sphinx httpdomain contrib package ``sphinxcontrib-httpdomain`` +* Install sphinx: `pip install sphinx` + * Mac OS X: `[sudo] pip-2.7 install sphinx`) +* Install sphinx httpdomain contrib package: `pip install sphinxcontrib-httpdomain` + * Mac OS X: `[sudo] pip-2.7 install sphinxcontrib-httpdomain` * If pip is not available you can probably install it using your favorite package manager as **python-pip** Usage From 01ce63aacdd975130244f4be70bc90736e85d457 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:26:54 -0700 Subject: [PATCH 49/79] Make style consistent --- docs/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/README.md b/docs/README.md index 54588e995d..74ab2bd0cd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -22,14 +22,14 @@ Installation Usage ----- -* change the .rst files with your favorite editor to your liking -* run *make docs* to clean up old files and generate new ones -* your static website can now be found in the _build dir -* to preview what you have generated run `make server` and open in your favorite browser. +* Change the `.rst` files with your favorite editor to your liking. +* Run `make docs` to clean up old files and generate new ones. +* Your static website can now be found in the `_build` directory. +* To preview what you have generated run `make server` and open in your favorite browser. -Working using github's file editor +Working using GitHub's file editor ---------------------------------- -Alternatively, for small changes and typo's you might want to use github's built in file editor. It allows +Alternatively, for small changes and typo's you might want to use GitHub's built in file editor. It allows you to preview your changes right online. Just be carefull not to create many commits. Images @@ -74,4 +74,4 @@ Guides on using sphinx * Code examples - Start without $, so it's easy to copy and paste. \ No newline at end of file + Start without $, so it's easy to copy and paste. From e3fd61ad74521b1a94502cf8dcc7c450f035c168 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:27:27 -0700 Subject: [PATCH 50/79] Add more tags --- docs/sources/examples/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sources/examples/index.rst b/docs/sources/examples/index.rst index 7eb2ecbe94..3a8e01fe03 100644 --- a/docs/sources/examples/index.rst +++ b/docs/sources/examples/index.rst @@ -1,6 +1,6 @@ :title: Docker Examples :description: Examples on how to use Docker -:keywords: docker, hello world, examples +:keywords: docker, hello world, python, couch, couchdb, redis, ssh, sshd, examples From f6f345b1fe0ecc1adba449b0078d96388dd48892 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:55:01 -0700 Subject: [PATCH 51/79] Fix typo --- docs/sources/api/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/api/index.rst b/docs/sources/api/index.rst index 4d8ff3fe67..85770f484e 100644 --- a/docs/sources/api/index.rst +++ b/docs/sources/api/index.rst @@ -2,8 +2,8 @@ :description: docker documentation :keywords: docker, ipa, documentation -API's -============= +APIs +==== This following : From 23452f1573e7887b638a4e69a4cf90d757921885 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 22:02:24 -0700 Subject: [PATCH 52/79] Use em dash in title --- docs/sources/concepts/introduction.rst | 4 ++-- docs/sources/index.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sources/concepts/introduction.rst b/docs/sources/concepts/introduction.rst index fcdd37a791..7251b51786 100644 --- a/docs/sources/concepts/introduction.rst +++ b/docs/sources/concepts/introduction.rst @@ -5,8 +5,8 @@ Introduction ============ -Docker - The Linux container runtime ------------------------------------- +Docker -- The Linux container runtime +------------------------------------- Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. diff --git a/docs/sources/index.rst b/docs/sources/index.rst index 172f82083c..3e66fde1fb 100644 --- a/docs/sources/index.rst +++ b/docs/sources/index.rst @@ -7,8 +7,8 @@ Introduction ============ -Docker - The Linux container runtime ------------------------------------- +Docker -- The Linux container runtime +------------------------------------- Docker complements LXC with a high-level API which operates at the process level. It runs unix processes with strong guarantees of isolation and repeatability across servers. From 2935ca7ee2879723c786b86ee87cc1be26dad7b8 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 22:03:12 -0700 Subject: [PATCH 53/79] Use title case for consistency --- docs/sources/contributing/devenvironment.rst | 4 ++-- docs/sources/examples/running_examples.rst | 2 +- docs/sources/use/basics.rst | 4 ++-- docs/sources/use/workingwithrepository.rst | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/sources/contributing/devenvironment.rst b/docs/sources/contributing/devenvironment.rst index 0d202596c8..b5742c780a 100644 --- a/docs/sources/contributing/devenvironment.rst +++ b/docs/sources/contributing/devenvironment.rst @@ -1,8 +1,8 @@ -:title: Setting up a dev environment +:title: Setting Up a Dev Environment :description: Guides on how to contribute to docker :keywords: Docker, documentation, developers, contributing, dev environment -Setting up a dev environment +Setting Up a Dev Environment ============================ Instructions that have been verified to work on Ubuntu 12.10, diff --git a/docs/sources/examples/running_examples.rst b/docs/sources/examples/running_examples.rst index 3d2593c710..b6d6444aac 100644 --- a/docs/sources/examples/running_examples.rst +++ b/docs/sources/examples/running_examples.rst @@ -4,7 +4,7 @@ .. _running_examples: -Running The Examples +Running the Examples -------------------- All the examples assume your machine is running the docker daemon. To run the docker daemon in the background, simply type: diff --git a/docs/sources/use/basics.rst b/docs/sources/use/basics.rst index 378028703c..444b74db51 100644 --- a/docs/sources/use/basics.rst +++ b/docs/sources/use/basics.rst @@ -3,8 +3,8 @@ :keywords: Examples, Usage, basic commands, docker, documentation, examples -The basics -============= +The Basics +========== Starting Docker --------------- diff --git a/docs/sources/use/workingwithrepository.rst b/docs/sources/use/workingwithrepository.rst index 9a2f96cf0d..db40245374 100644 --- a/docs/sources/use/workingwithrepository.rst +++ b/docs/sources/use/workingwithrepository.rst @@ -4,8 +4,8 @@ .. _working_with_the_repository: -Working with the repository -============================ +Working with the Repository +=========================== Top-level repositories and user repositories From 157547845acd8a0633df72e01d22bad9cbec578b Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 22:03:28 -0700 Subject: [PATCH 54/79] Name examples consistently --- docs/sources/examples/couchdb_data_volumes.rst | 4 ++-- docs/sources/examples/python_web_app.rst | 4 ++-- docs/sources/examples/running_redis_service.rst | 4 ++-- docs/sources/examples/running_ssh_service.rst | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/sources/examples/couchdb_data_volumes.rst b/docs/sources/examples/couchdb_data_volumes.rst index 1b1d7ff79c..d6babe557f 100644 --- a/docs/sources/examples/couchdb_data_volumes.rst +++ b/docs/sources/examples/couchdb_data_volumes.rst @@ -4,8 +4,8 @@ .. _running_couchdb_service: -Create a CouchDB service -======================== +CouchDB Service +=============== .. include:: example_header.inc diff --git a/docs/sources/examples/python_web_app.rst b/docs/sources/examples/python_web_app.rst index 952ef62e33..8a4ca70750 100644 --- a/docs/sources/examples/python_web_app.rst +++ b/docs/sources/examples/python_web_app.rst @@ -4,8 +4,8 @@ .. _python_web_app: -Building a python web app -========================= +Python Web App +============== .. include:: example_header.inc diff --git a/docs/sources/examples/running_redis_service.rst b/docs/sources/examples/running_redis_service.rst index 4b5d161e61..48d083aa8f 100644 --- a/docs/sources/examples/running_redis_service.rst +++ b/docs/sources/examples/running_redis_service.rst @@ -4,8 +4,8 @@ .. _running_redis_service: -Create a redis service -====================== +Redis Service +============= .. include:: example_header.inc diff --git a/docs/sources/examples/running_ssh_service.rst b/docs/sources/examples/running_ssh_service.rst index b262266dec..6183c3a55d 100644 --- a/docs/sources/examples/running_ssh_service.rst +++ b/docs/sources/examples/running_ssh_service.rst @@ -4,8 +4,8 @@ .. _running_ssh_service: -Create an ssh daemon service -============================ +SSH Daemon Service +================== .. include:: example_header.inc From 4fb9a6eafb981ed66fe547fe29c11525f40d0640 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 22:03:41 -0700 Subject: [PATCH 55/79] Use code blocks --- docs/sources/use/workingwithrepository.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sources/use/workingwithrepository.rst b/docs/sources/use/workingwithrepository.rst index db40245374..6fccc01a98 100644 --- a/docs/sources/use/workingwithrepository.rst +++ b/docs/sources/use/workingwithrepository.rst @@ -14,9 +14,9 @@ Top-level repositories and user repositories Generally, there are two types of repositories: Top-level repositories which are controlled by the people behind Docker, and user repositories. -* Top-level repositories can easily be recognized by not having a / (slash) in their name. These repositories can +* Top-level repositories can easily be recognized by not having a ``/`` (slash) in their name. These repositories can generally be trusted. -* User repositories always come in the form of /. This is what your published images will look like. +* User repositories always come in the form of ``/``. This is what your published images will look like. * User images are not checked, it is therefore up to you whether or not you trust the creator of this image. From e9ffc1e49998d42f37b39cd23b56b73f7dc0e3da Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 21:53:22 -0700 Subject: [PATCH 56/79] Add Node.js web app example using CentOS --- docs/sources/examples/index.rst | 3 +- docs/sources/examples/nodejs_web_app.rst | 225 +++++++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 docs/sources/examples/nodejs_web_app.rst diff --git a/docs/sources/examples/index.rst b/docs/sources/examples/index.rst index 3a8e01fe03..d017f641b1 100644 --- a/docs/sources/examples/index.rst +++ b/docs/sources/examples/index.rst @@ -1,6 +1,6 @@ :title: Docker Examples :description: Examples on how to use Docker -:keywords: docker, hello world, python, couch, couchdb, redis, ssh, sshd, examples +:keywords: docker, hello world, node, nodejs, python, couch, couchdb, redis, ssh, sshd, examples @@ -16,6 +16,7 @@ Contents: hello_world hello_world_daemon python_web_app + nodejs_web_app running_redis_service running_ssh_service couchdb_data_volumes diff --git a/docs/sources/examples/nodejs_web_app.rst b/docs/sources/examples/nodejs_web_app.rst new file mode 100644 index 0000000000..7c1df83776 --- /dev/null +++ b/docs/sources/examples/nodejs_web_app.rst @@ -0,0 +1,225 @@ +:title: Running a Node.js app on CentOS +:description: Installing and running a Node.js app on CentOS +:keywords: docker, example, package installation, node, centos + +.. _nodejs_web_app: + +Node.js Web App +=============== + +.. include:: example_header.inc + +The goal of this example is to show you how you can build your own docker images +from a parent image using a ``Dockerfile`` . We will do that by making a simple +Node.js hello world web application running on CentOS. + +Create Node.js app +++++++++++++++++++ + +First, create a ``package.json`` file that describes your app and its +dependencies: + +.. code-block:: json + + { + "name": "docker-centos-hello", + "private": true, + "version": "0.0.1", + "description": "Node.js Hello World app on CentOS using docker", + "author": "Daniel Gasienica ", + "dependencies": { + "express": "3.2.4" + } + } + +Then, create an ``index.js`` file that defines a web app using the +`Express.js `_ framework: + +.. code-block:: javascript + + var express = require('express'); + + // Constants + var PORT = 8080; + + // App + var app = express(); + app.get('/', function (req, res) { + res.send('Hello World\n'); + }); + + app.listen(PORT) + console.log('Running on http://localhost:' + PORT); + + +In the next steps, we’ll look at how you can run this app inside a CentOS +container using docker. First, you’ll need to build a docker image of your app. + +Creating a ``Dockerfile`` ++++++++++++++++++++++++++ + +Create an empty file called ``Dockerfile``: + +.. code-block:: bash + + touch Dockerfile + +Open the ``Dockerfile`` in your favorite text editor and add the following line +that defines the version of docker the image requires to build +(this example uses docker 0.3.4): + +.. code-block:: bash + + # DOCKER-VERSION 0.3.4 + +Next, define the parent image you want to use to build your own image on top of. +Here, we’ll use `CentOS `_ (tag: ``6.4``) +available on the `docker index`_: + +.. code-block:: bash + + FROM centos:6.4 + +Since we’re building a Node.js app, you’ll have to install Node.js as well as +npm on your CentOS image. Node.js is required to run your app and npm to install +your app’s dependencies defined in ``package.json``. +To install the right package for CentOS, we’ll use the instructions from the +`Node.js wiki`_: + +.. code-block:: bash + + # Enable EPEL for Node.js + RUN rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm + # Install Node.js and npm + RUN yum install -y npm-1.2.17-5.el6 + +To bundle your app’s source code inside the docker image, use the ``ADD`` +command: + +.. code-block:: bash + + # Bundle app source + ADD . /src + +Your app binds to port ``8080`` so you’ll use the ``EXPOSE`` command to have it +mapped by the docker daemon: + +.. code-block:: bash + + EXPOSE 8080 + +Last but not least, define the command to run your app using ``CMD`` which +defines your runtime, i.e. ``node``, and the path to our app, i.e. +``src/index.js`` (see the step where we added the source to the container): + +.. code-block:: bash + + CMD ["node", "/src/index.js"] + +Your ``Dockerfile`` should now look like this: + +.. code-block:: bash + + + # DOCKER-VERSION 0.3.4 + FROM centos:6.4 + + # Enable EPEL for Node.js + RUN rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm + # Install Node.js and npm + RUN yum install -y npm-1.2.17-5.el6 + + # Bundle app source + ADD . /src + EXPOSE 8080 + CMD ["node", "/src/index.js"] + + +Building your image ++++++++++++++++++++ + +Go to the directory that has your ``Dockerfile`` and run the following command +to build a docker image. The ``-t`` flag let’s you tag your image so it’s easier +to find later using the ``docker images`` command: + +.. code-block:: bash + + docker build -t /centos-node-hello . + +Your image will now be listed by docker: + +.. code-block:: bash + + docker images + + > # Example + > REPOSITORY TAG ID CREATED + > centos 6.4 539c0211cd76 8 weeks ago + > gasi/centos-node-hello latest d64d3505b0d2 2 hours ago + + +Run the image ++++++++++++++ + +Running your image with ``-d`` runs the container in detached mode, leaving the +container running in the background. Run the image you previously built: + +.. code-block:: bash + + docker run -d /centos-node-hello + +Print the output of your app: + +.. code-block:: bash + + # Get container ID + docker ps + + # Print app output + docker logs + + > # Example + > Running on http://localhost:8080 + + +Test +++++ + +To test your app, get the the port of your app that docker mapped: + +.. code-block:: bash + + docker ps + + > # Example + > ID IMAGE COMMAND ... PORTS + > ecce33b30ebf gasi/centos-node-hello:latest node /src/index.js 49160->8080 + +In the example above, docker mapped the ``8080`` port of the container to +``49160``. + +Now you can call your app using ``curl`` (install if needed via: +``sudo apt-get install curl``): + +.. code-block:: bash + + curl -i localhost:49160 + + > HTTP/1.1 200 OK + > X-Powered-By: Express + > Content-Type: text/html; charset=utf-8 + > Content-Length: 12 + > Date: Sun, 02 Jun 2013 03:53:22 GMT + > Connection: keep-alive + > + > Hello World + +We hope this tutorial helped you get up and running with Node.js and CentOS on +docker. You can get the full source code at +https://github.com/gasi/docker-node-hello. + +Continue to :ref:`running_redis_service`. + + +.. _Node.js wiki: https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#rhelcentosscientific-linux-6 +.. _docker index: https://index.docker.io/ From 464765b940c8194c302b89891dc06b8fcc1b37ff Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 1 Jun 2013 22:16:26 -0700 Subject: [PATCH 57/79] Add link at the beginning --- docs/sources/examples/nodejs_web_app.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/sources/examples/nodejs_web_app.rst b/docs/sources/examples/nodejs_web_app.rst index 7c1df83776..56dab0c9aa 100644 --- a/docs/sources/examples/nodejs_web_app.rst +++ b/docs/sources/examples/nodejs_web_app.rst @@ -11,7 +11,8 @@ Node.js Web App The goal of this example is to show you how you can build your own docker images from a parent image using a ``Dockerfile`` . We will do that by making a simple -Node.js hello world web application running on CentOS. +Node.js hello world web application running on CentOS. You can get the full +source code at https://github.com/gasi/docker-node-hello. Create Node.js app ++++++++++++++++++ From ca5ae266b762d34075524d869e27f0daaa79265c Mon Sep 17 00:00:00 2001 From: Sam J Sharpe Date: Sun, 2 Jun 2013 22:40:56 +0100 Subject: [PATCH 58/79] Removes a brace in the description of the wait command --- commands.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands.go b/commands.go index 7dd835856f..76b70cd218 100644 --- a/commands.go +++ b/commands.go @@ -102,7 +102,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error { {"stop", "Stop a running container"}, {"tag", "Tag an image into a repository"}, {"version", "Show the docker version information"}, - {"wait", "Block until a container stops}, then print its exit code"}, + {"wait", "Block until a container stops, then print its exit code"}, } { help += fmt.Sprintf(" %-10.10s%s\n", command[0], command[1]) } From 82dadc200593e39f0979159d46afccf64f1e7a83 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sun, 2 Jun 2013 20:10:22 -0700 Subject: [PATCH 59/79] Document installation of npm dependencies /ht @grigio --- docs/sources/examples/nodejs_web_app.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/sources/examples/nodejs_web_app.rst b/docs/sources/examples/nodejs_web_app.rst index 56dab0c9aa..376dc5c286 100644 --- a/docs/sources/examples/nodejs_web_app.rst +++ b/docs/sources/examples/nodejs_web_app.rst @@ -102,6 +102,13 @@ command: # Bundle app source ADD . /src +Install your app dependencies using npm: + +.. code-block:: bash + + # Install app dependencies + RUN cd /src; npm install + Your app binds to port ``8080`` so you’ll use the ``EXPOSE`` command to have it mapped by the docker daemon: @@ -132,6 +139,9 @@ Your ``Dockerfile`` should now look like this: # Bundle app source ADD . /src + # Install app dependencies + RUN cd /src; npm install + EXPOSE 8080 CMD ["node", "/src/index.js"] From e42eb7fa8c22e7451e06c28d9125fc7534239c89 Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Sun, 2 Jun 2013 23:42:18 -0700 Subject: [PATCH 60/79] Meta: added Guillaume as primary maintainer for tty code --- term/MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 term/MAINTAINERS diff --git a/term/MAINTAINERS b/term/MAINTAINERS new file mode 100644 index 0000000000..8df21a4601 --- /dev/null +++ b/term/MAINTAINERS @@ -0,0 +1,2 @@ +Guillaume Charmes +Solomon Hykes From e16c93486d16ac4f3a05f720ee6478b5cef93f10 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 3 Jun 2013 10:19:20 +0000 Subject: [PATCH 61/79] fix Path corruption in 'docker diff' --- changes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes.go b/changes.go index 4c79918887..e50b88758a 100644 --- a/changes.go +++ b/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 := strings.TrimPrefix(file, ".wh.") change.Path = filepath.Join(filepath.Dir(path), originalFile) change.Kind = ChangeDelete } else { From 8243f2510e0ff0af8df18bf0febab819529106d4 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 3 Jun 2013 06:44:00 -0700 Subject: [PATCH 62/79] Update test to reflect new ApiInfo struct --- api_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api_test.go b/api_test.go index f364c6c895..9121167e10 100644 --- a/api_test.go +++ b/api_test.go @@ -106,8 +106,8 @@ func TestGetInfo(t *testing.T) { 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) } } From 1ce4ba6c9f381f7931615644675b0cad33e74492 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 3 Jun 2013 15:33:29 +0000 Subject: [PATCH 63/79] remove check on login --- commands.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/commands.go b/commands.go index 9f3168ac06..ddb2c1a52b 100644 --- a/commands.go +++ b/commands.go @@ -739,12 +739,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) From 71b1657e8d22b6dfa0a426f6244c6a3101f66bc4 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 3 Jun 2013 17:02:57 +0000 Subject: [PATCH 64/79] added test --- container_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/container_test.go b/container_test.go index 3ed1763a3e..117f0f3eb3 100644 --- a/container_test.go +++ b/container_test.go @@ -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) { From 854039b6ba9c707af07f9966b39150ce23150920 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Mon, 3 Jun 2013 17:25:51 +0000 Subject: [PATCH 65/79] remove TrimLeft as it's go1.1 --- changes.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changes.go b/changes.go index e50b88758a..dc1b015726 100644 --- a/changes.go +++ b/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.TrimPrefix(file, ".wh.") + originalFile := file[len(".wh."):] change.Path = filepath.Join(filepath.Dir(path), originalFile) change.Kind = ChangeDelete } else { From a8ae398bf52e97148ee7bd0d5868de2e15bd297f Mon Sep 17 00:00:00 2001 From: Solomon Hykes Date: Mon, 3 Jun 2013 10:59:48 -0700 Subject: [PATCH 66/79] Bumped version to 0.4.0 --- CHANGELOG.md | 5 +++++ commands.go | 2 +- packaging/ubuntu/changelog | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8464b5345..44e52eecb5 100644 --- a/CHANGELOG.md +++ b/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/commands.go b/commands.go index ddb2c1a52b..c38c18a04c 100644 --- a/commands.go +++ b/commands.go @@ -28,7 +28,7 @@ import ( "unicode" ) -const VERSION = "0.3.4" +const VERSION = "0.4.0" var ( GIT_COMMIT string diff --git a/packaging/ubuntu/changelog b/packaging/ubuntu/changelog index 10151ed483..5fc2e49d5e 100644 --- a/packaging/ubuntu/changelog +++ b/packaging/ubuntu/changelog @@ -1,3 +1,10 @@ +lxc-docker (0.4.0-1) precise; urgency=low + - 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 + + -- dotCloud Mon, 03 Jun 2013 00:00:00 -0700 + lxc-docker (0.3.4-1) precise; urgency=low - 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. From 38f29f7d0c9cbdb4c458834d403fc128dcce3117 Mon Sep 17 00:00:00 2001 From: Thatcher Peskens Date: Mon, 3 Jun 2013 11:45:19 -0700 Subject: [PATCH 67/79] Changed some text on the website to include docker-club Fixed a link in the FAQ on the docs Fixed a detail in the Makefile for pushing the site to dotcloud --- docs/Makefile | 2 +- docs/sources/faq.rst | 7 +++---- docs/sources/installation/windows.rst | 1 + docs/website/gettingstarted/index.html | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/Makefile b/docs/Makefile index dcbf111c29..517d01658f 100644 --- a/docs/Makefile +++ b/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/docs/sources/faq.rst b/docs/sources/faq.rst index 901e51ddbb..dfffa012f4 100644 --- a/docs/sources/faq.rst +++ b/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?** @@ -39,10 +40,8 @@ Most frequently asked questions. * `Ask questions on Stackoverflow`_ * `Join the conversation on Twitter`_ - .. _Windows: ../installation/windows/ - .. _MacOSX: ../installation/vagrant/ .. _the repo: http://www.github.com/dotcloud/docker - .. _IRC\: docker on freenode: irc://chat.freenode.net#docker + .. _IRC: docker on freenode: 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/docs/sources/installation/windows.rst b/docs/sources/installation/windows.rst index 230ac78051..7830106020 100644 --- a/docs/sources/installation/windows.rst +++ b/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/docs/website/gettingstarted/index.html b/docs/website/gettingstarted/index.html index 5a8de3232b..a40289144f 100644 --- a/docs/website/gettingstarted/index.html +++ b/docs/website/gettingstarted/index.html @@ -62,7 +62,7 @@
    -
    +
    Docker is still under heavy development. It should not yet be used in production. Check the repo for recent progress.
    @@ -133,13 +133,13 @@
    -

    More resources

    - +

    Questions? Want to get in touch?

    +

    There are several ways to get in touch:

    +

    Join the discussion on IRC. We can be found in the #docker channel on chat.freenode.net

    +

    Discussions happen on our google group: docker-club at googlegroups.com

    +

    All our development and decisions are made out in the open on Github github.com/dotcloud/docker

    +

    Get help on using Docker by asking on Stackoverflow

    +

    And of course, tweet your tweets to twitter.com/getdocker

    From 830c458fe761aca5ad2facec33b3d0798caab116 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 3 Jun 2013 12:14:57 -0700 Subject: [PATCH 68/79] Fixed missing Body.Close when doing some HTTP requests. It should improve some request issues. --- registry/registry.go | 7 ++++++- server.go | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/registry/registry.go b/registry/registry.go index 36b01d643a..d9f53ee9f9 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -64,6 +64,9 @@ func (r *Registry) LookupRemoteImage(imgId, registry string, authConfig *auth.Au } req.SetBasicAuth(authConfig.Username, authConfig.Password) res, err := rt.RoundTrip(req) + if err == nil { + defer res.Body.Close() + } return err == nil && res.StatusCode == 307 } @@ -152,7 +155,9 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ } req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) res, err := r.client.Do(req) - defer res.Body.Close() + if err == nil { + defer res.Body.Close() + } utils.Debugf("Got status code %d from %s", res.StatusCode, endpoint) if err != nil || (res.StatusCode != 200 && res.StatusCode != 404) { continue diff --git a/server.go b/server.go index fa847b9ce5..08cb37a72e 100644 --- a/server.go +++ b/server.go @@ -321,6 +321,7 @@ func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgId, endpoin if err != nil { return err } + defer layer.Close() if err := srv.runtime.graph.Register(utils.ProgressReader(layer, contentLength, out, sf.FormatProgress("Downloading", "%v/%v (%v)"), sf), false, img); err != nil { return err } From 82dd963e08778f8c563e058f1b19ccc358965615 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Mon, 3 Jun 2013 12:20:52 -0700 Subject: [PATCH 69/79] Minor changes in registry.go --- registry/registry.go | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/registry/registry.go b/registry/registry.go index d9f53ee9f9..8283bf4437 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -64,10 +64,11 @@ func (r *Registry) LookupRemoteImage(imgId, registry string, authConfig *auth.Au } req.SetBasicAuth(authConfig.Username, authConfig.Password) res, err := rt.RoundTrip(req) - if err == nil { - defer res.Body.Close() + if err != nil { + return false } - return err == nil && res.StatusCode == 307 + res.Body.Close() + return res.StatusCode == 307 } func (r *Registry) getImagesInRepository(repository string, authConfig *auth.AuthConfig) ([]map[string]string, error) { @@ -155,18 +156,19 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ } req.Header.Set("Authorization", "Token "+strings.Join(token, ", ")) res, err := r.client.Do(req) - if err == nil { - defer res.Body.Close() - } utils.Debugf("Got status code %d from %s", res.StatusCode, endpoint) - if err != nil || (res.StatusCode != 200 && res.StatusCode != 404) { + if err != nil { + return nil, err + } + defer res.Body.Close() + + if res.StatusCode != 200 && res.StatusCode != 404 { continue } else if res.StatusCode == 404 { return nil, fmt.Errorf("Repository not found") } result := make(map[string]string) - rawJson, err := ioutil.ReadAll(res.Body) if err != nil { return nil, err From cff3b37a61b8da883437eec799b7b852d22538f0 Mon Sep 17 00:00:00 2001 From: Sam Alba Date: Mon, 3 Jun 2013 14:42:21 -0700 Subject: [PATCH 70/79] Disabled HTTP keep-alive in the default HTTP client for Registry calls --- registry/registry.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/registry/registry.go b/registry/registry.go index 8283bf4437..aeae3fe4a4 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -477,9 +477,15 @@ func NewRegistry(root string) *Registry { // If the auth file does not exist, keep going authConfig, _ := auth.LoadConfig(root) + httpTransport := &http.Transport{ + DisableKeepAlives: true, + } + r := &Registry{ authConfig: authConfig, - client: &http.Client{}, + client: &http.Client{ + Transport: httpTransport, + }, } r.client.Jar = cookiejar.NewCookieJar() return r From b515a5a9ec5792c67be5fe8476df96903f43df71 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 4 Jun 2013 13:24:58 +0000 Subject: [PATCH 71/79] go vet --- container.go | 2 -- network.go | 1 - 2 files changed, 3 deletions(-) diff --git a/container.go b/container.go index c6b7c8a51c..e552fba036 100644 --- a/container.go +++ b/container.go @@ -606,7 +606,6 @@ func (container *Container) waitLxc() error { } time.Sleep(500 * time.Millisecond) } - return nil } func (container *Container) monitor() { @@ -795,7 +794,6 @@ func (container *Container) WaitTimeout(timeout time.Duration) error { case <-done: return nil } - panic("unreachable") } func (container *Container) EnsureMounted() error { diff --git a/network.go b/network.go index 77a82ed9f0..dbf5480f1c 100644 --- a/network.go +++ b/network.go @@ -258,7 +258,6 @@ func proxy(listener net.Listener, proto, address string) error { utils.Debugf("Connected to backend, splicing") splice(src, dst) } - return nil } func halfSplice(dst, src net.Conn) error { From 86ada2fa5d00820288df8a59eca3deef83f4aeb6 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 4 Jun 2013 13:51:12 +0000 Subject: [PATCH 72/79] drop/omit --- auth/auth.go | 2 +- builder_client.go | 6 +++--- buildfile.go | 6 +++--- commands.go | 31 +++++++++++++++---------------- container.go | 30 +++++++++++++++--------------- contrib/crashTest.go | 2 +- image.go | 3 +-- network.go | 9 ++++----- registry/registry.go | 8 ++++---- runtime.go | 36 ++++++++++++++++++------------------ server.go | 15 +++++++-------- utils/utils.go | 2 +- 12 files changed, 73 insertions(+), 77 deletions(-) diff --git a/auth/auth.go b/auth/auth.go index 9c34604419..a57d019dce 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -21,7 +21,7 @@ const INDEX_SERVER = "https://index.docker.io/v1" //const INDEX_SERVER = "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 { diff --git a/builder_client.go b/builder_client.go index 144e11b415..4ea2a9f95f 100644 --- a/builder_client.go +++ b/builder_client.go @@ -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 } diff --git a/buildfile.go b/buildfile.go index a015830e0d..fb5c1c9d5c 100644 --- a/buildfile.go +++ b/buildfile.go @@ -272,11 +272,11 @@ func (b *buildFile) commit(id string, autoCmd []string, comment string) error { 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) diff --git a/commands.go b/commands.go index c38c18a04c..943b2198c1 100644 --- a/commands.go +++ b/commands.go @@ -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 { @@ -1417,11 +1416,11 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi }) if in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" { - if oldState, err := term.SetRawTerminal(); err != nil { + 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) diff --git a/container.go b/container.go index e552fba036..9c28e5aa23 100644 --- a/container.go +++ b/container.go @@ -431,14 +431,14 @@ 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 != "" { @@ -573,12 +573,12 @@ 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 @@ -597,12 +597,12 @@ 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) } @@ -625,7 +625,7 @@ func (container *Container) monitor() { } utils.Debugf("Process finished") - var exitCode int = -1 + exitCode := -1 if container.cmd != nil { exitCode = container.cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus() } diff --git a/contrib/crashTest.go b/contrib/crashTest.go index d4a889e8d3..320e97c52a 100644 --- a/contrib/crashTest.go +++ b/contrib/crashTest.go @@ -11,7 +11,7 @@ import ( "time" ) -var DOCKER_PATH string = path.Join(os.Getenv("DOCKERPATH"), "docker") +var DOCKER_PATH = path.Join(os.Getenv("DOCKERPATH"), "docker") // WARNING: this crashTest will 1) crash your host, 2) remove all containers func runDaemon() (*exec.Cmd, error) { diff --git a/image.go b/image.go index d825b4bba2..3617d7dd19 100644 --- a/image.go +++ b/image.go @@ -49,9 +49,8 @@ func LoadImage(root string) (*Image, error) { if stat, err := os.Stat(layerPath(root)); err != nil { if os.IsNotExist(err) { return nil, fmt.Errorf("Couldn't load image %s: no filesystem layer", img.Id) - } else { - return nil, err } + return nil, err } else if !stat.IsDir() { return nil, fmt.Errorf("Couldn't load image %s: %s is not a directory", img.Id, layerPath(root)) } diff --git a/network.go b/network.go index dbf5480f1c..2bdb4862ce 100644 --- a/network.go +++ b/network.go @@ -132,9 +132,8 @@ func CreateBridgeIface(ifaceName string) error { } if ifaceAddr == "" { return fmt.Errorf("Could not find a free IP address range for interface '%s'. Please configure its address manually and run 'docker -b %s'", ifaceName, ifaceName) - } else { - utils.Debugf("Creating bridge %s with network %s", ifaceName, ifaceAddr) } + utils.Debugf("Creating bridge %s with network %s", ifaceName, ifaceAddr) if output, err := ip("link", "add", ifaceName, "type", "bridge"); err != nil { return fmt.Errorf("Error creating bridge: %s (output: %s)", err, output) @@ -464,11 +463,11 @@ func (iface *NetworkInterface) AllocatePort(spec string) (*Nat, error) { return nil, err } // Allocate a random port if Frontend==0 - if extPort, err := iface.manager.portAllocator.Acquire(nat.Frontend); err != nil { + extPort, err := iface.manager.portAllocator.Acquire(nat.Frontend) + if err != nil { return nil, err - } else { - nat.Frontend = extPort } + nat.Frontend = extPort if err := iface.manager.portMapper.Map(nat.Frontend, net.TCPAddr{IP: iface.IPNet.IP, Port: nat.Backend}); err != nil { iface.manager.portAllocator.Release(nat.Frontend) return nil, err diff --git a/registry/registry.go b/registry/registry.go index aeae3fe4a4..b6cda92841 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -15,7 +15,7 @@ import ( "strings" ) -var ErrAlreadyExists error = errors.New("Image already exists") +var ErrAlreadyExists = errors.New("Image already exists") func doWithCookies(c *http.Client, req *http.Request) (*http.Response, error) { for _, cookie := range c.Jar.Cookies(req.URL) { @@ -396,11 +396,11 @@ func (r *Registry) PushImageJsonIndex(remote string, imgList []*ImgData, validat } if validate { if res.StatusCode != 204 { - if errBody, err := ioutil.ReadAll(res.Body); err != nil { + errBody, err := ioutil.ReadAll(res.Body) + if err != nil { return nil, err - } else { - return nil, fmt.Errorf("Error: Status %d trying to push checksums %s: %s", res.StatusCode, remote, errBody) } + return nil, fmt.Errorf("Error: Status %d trying to push checksums %s: %s", res.StatusCode, remote, errBody) } } diff --git a/runtime.go b/runtime.go index 3c190e934e..ad1852e902 100644 --- a/runtime.go +++ b/runtime.go @@ -133,25 +133,25 @@ func (runtime *Runtime) Register(container *Container) error { // if so, then we need to restart monitor and init a new lock // If the container is supposed to be running, make sure of it if container.State.Running { - 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") { - utils.Debugf("Container %s was supposed to be running be is not.", container.Id) - if runtime.autoRestart { - utils.Debugf("Restarting") - container.State.Ghost = false - container.State.setStopped(0) - if err := container.Start(); err != nil { - return err - } - nomonitor = true - } else { - utils.Debugf("Marking as stopped") - container.State.setStopped(-127) - if err := container.ToDisk(); err != nil { - return err - } + } + if !strings.Contains(string(output), "RUNNING") { + utils.Debugf("Container %s was supposed to be running be is not.", container.Id) + if runtime.autoRestart { + utils.Debugf("Restarting") + container.State.Ghost = false + container.State.setStopped(0) + if err := container.Start(); err != nil { + return err + } + nomonitor = true + } else { + utils.Debugf("Marking as stopped") + container.State.setStopped(-127) + if err := container.ToDisk(); err != nil { + return err } } } diff --git a/server.go b/server.go index 08cb37a72e..9e98b87c21 100644 --- a/server.go +++ b/server.go @@ -216,7 +216,7 @@ func (srv *Server) ImageHistory(name string) ([]ApiHistory, error) { return nil, err } - var outs []ApiHistory = []ApiHistory{} //produce [] when empty instead of 'null' + outs := []ApiHistory{} //produce [] when empty instead of 'null' err = image.WalkHistory(func(img *Image) error { var out ApiHistory out.Id = srv.runtime.repositories.ImageName(img.ShortId()) @@ -356,11 +356,11 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, a } } else { // Otherwise, check that the tag exists and use only that one - if id, exists := tagsList[askedTag]; !exists { + id, exists := tagsList[askedTag] + if !exists { return fmt.Errorf("Tag %s not found in repositoy %s", askedTag, remote) - } else { - repoData.ImgList[id].Tag = askedTag } + repoData.ImgList[id].Tag = askedTag } for _, img := range repoData.ImgList { @@ -714,10 +714,9 @@ func (srv *Server) ImageDelete(name string) error { img, err := srv.runtime.repositories.LookupImage(name) if err != nil { return fmt.Errorf("No such image: %s", name) - } else { - if err := srv.runtime.graph.Delete(img.Id); err != nil { - return fmt.Errorf("Error deleting image %s: %s", name, err.Error()) - } + } + if err := srv.runtime.graph.Delete(img.Id); err != nil { + return fmt.Errorf("Error deleting image %s: %s", name, err.Error()) } return nil } diff --git a/utils/utils.go b/utils/utils.go index 33aa2eba8c..eb6b35677e 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -34,7 +34,7 @@ func Go(f func() error) chan error { // Request a given URL and return an io.Reader func Download(url string, stderr io.Writer) (*http.Response, error) { var resp *http.Response - var err error = nil + var err error if resp, err = http.Get(url); err != nil { return nil, err } From e61af8bc62c84a1bc70d0b323c1b6bf21dddb4b6 Mon Sep 17 00:00:00 2001 From: John Costa Date: Mon, 3 Jun 2013 17:29:41 -0400 Subject: [PATCH 73/79] some installations of ubuntu 13.04 (digital ocean Ubuntu 13.04 x64 Server in this case) require software-properties-common to be installed before being able to use add-apt-repository --- docs/sources/installation/ubuntulinux.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/sources/installation/ubuntulinux.rst b/docs/sources/installation/ubuntulinux.rst index 1fb1ce5299..5ccbd59c29 100644 --- a/docs/sources/installation/ubuntulinux.rst +++ b/docs/sources/installation/ubuntulinux.rst @@ -92,6 +92,17 @@ 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 (Digital Ocean's Ubuntu 13.04 x64 Server in +this case) 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 ------------ From 06b585ce8a397fffcc9051e2faa6f968e51fccd5 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 4 Jun 2013 15:44:27 +0000 Subject: [PATCH 74/79] fix proxy --- registry/registry.go | 1 + 1 file changed, 1 insertion(+) diff --git a/registry/registry.go b/registry/registry.go index aeae3fe4a4..ede8eda722 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -479,6 +479,7 @@ func NewRegistry(root string) *Registry { httpTransport := &http.Transport{ DisableKeepAlives: true, + Proxy: http.ProxyFromEnvironment, } r := &Registry{ From 3922691fb99a99cec0a5d239da522cc3d8778e6c Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 4 Jun 2013 16:09:08 +0000 Subject: [PATCH 75/79] fix progress message in client --- commands.go | 2 +- docs/sources/api/docker_remote_api.rst | 6 +++--- server.go | 2 +- utils/utils.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/commands.go b/commands.go index c38c18a04c..93bae63a29 100644 --- a/commands.go +++ b/commands.go @@ -1379,7 +1379,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e 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 { diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index dca4599c55..1c46cf148a 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/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..."} ... diff --git a/server.go b/server.go index 08cb37a72e..ec2157d803 100644 --- a/server.go +++ b/server.go @@ -573,7 +573,7 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, } // Send the layer - if err := r.PushImageLayerRegistry(imgData.Id, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("", "%v/%v (%v)"), sf), ep, token); err != nil { + if err := r.PushImageLayerRegistry(imgData.Id, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("Pushing", "%v/%v (%v)"), sf), ep, token); err != nil { return err } return nil diff --git a/utils/utils.go b/utils/utils.go index 33aa2eba8c..2cd23ad6d2 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -608,7 +608,7 @@ func (sf *StreamFormatter) FormatError(err error) []byte { func (sf *StreamFormatter) FormatProgress(action, str string) []byte { sf.used = true if sf.json { - b, err := json.Marshal(&JsonMessage{Progress:str}) + b, err := json.Marshal(&JsonMessage{Status: action, Progress:str}) if err != nil { return nil } From fd224ee590dc9f003f6507b529a9f47cceb02c44 Mon Sep 17 00:00:00 2001 From: Victor Vieux Date: Tue, 4 Jun 2013 18:00:22 +0000 Subject: [PATCH 76/79] linted names --- api.go | 72 ++++++++++----------- api_params.go | 36 +++++------ api_test.go | 146 +++++++++++++++++++++---------------------- auth/auth.go | 6 +- builder.go | 10 +-- builder_client.go | 34 +++++----- buildfile.go | 14 ++--- buildfile_test.go | 6 +- commands.go | 62 +++++++++--------- container.go | 60 +++++++++--------- container_test.go | 68 ++++++++++---------- contrib/crashTest.go | 6 +- docker/docker.go | 4 +- graph.go | 42 ++++++------- graph_test.go | 22 +++---- image.go | 32 +++++----- lxc_template.go | 2 +- network.go | 4 +- network_test.go | 2 +- registry/registry.go | 36 +++++------ runtime.go | 30 ++++----- runtime_test.go | 50 +++++++-------- server.go | 116 +++++++++++++++++----------------- server_test.go | 4 +- tags.go | 26 ++++---- utils/utils.go | 12 ++-- 26 files changed, 451 insertions(+), 451 deletions(-) diff --git a/api.go b/api.go index 7666b79a5f..5a9bdbbe23 100644 --- a/api.go +++ b/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() @@ -52,7 +52,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) } @@ -82,7 +82,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 } @@ -111,11 +111,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) @@ -128,7 +128,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 } @@ -157,7 +157,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 } @@ -176,7 +176,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 } @@ -193,7 +193,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 } @@ -210,7 +210,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 } @@ -227,11 +227,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 } @@ -251,7 +251,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 } @@ -294,12 +294,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 } @@ -353,7 +353,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 } @@ -372,18 +372,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 } @@ -421,8 +421,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.") @@ -437,7 +437,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 } @@ -534,11 +534,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 } @@ -625,7 +625,7 @@ func getContainersByName(srv *Server, version float64, w http.ResponseWriter, r if err != nil { return err } - writeJson(w, b) + writeJSON(w, b) return nil } @@ -643,17 +643,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 } @@ -661,12 +661,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 } @@ -712,13 +712,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, @@ -767,9 +767,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/api_params.go b/api_params.go index e18238b735..b8596d854b 100644 --- a/api_params.go +++ b/api_params.go @@ -1,19 +1,19 @@ package docker -type ApiHistory struct { - Id string +type APIHistory struct { + ID string `json:"Id"` Created int64 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 { +type APIInfo struct { Debug bool Containers int Images int @@ -23,8 +23,8 @@ type ApiInfo struct { SwapLimit bool `json:",omitempty"` } -type ApiContainers struct { - Id string +type APIContainers struct { + ID string `json:"Id"` Image string Command string Created int64 @@ -32,39 +32,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 +type APIRun struct { + ID string `json:"Id"` Warnings []string `json:",omitempty"` } -type ApiPort struct { +type APIPort struct { Port string } -type ApiVersion struct { +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/api_test.go b/api_test.go index 9121167e10..e122786b86 100644 --- a/api_test.go +++ b/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,11 +97,11 @@ 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) @@ -111,7 +111,7 @@ func TestGetInfo(t *testing.T) { } } -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") } diff --git a/auth/auth.go b/auth/auth.go index a57d019dce..72cf36efa5 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -16,9 +16,9 @@ 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 = errors.New("The Auth config file is missing") @@ -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/builder.go b/builder.go index 5f56f65d05..808b7efcab 100644 --- a/builder.go +++ b/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/builder_client.go b/builder_client.go index 4ea2a9f95f..dc9528ff41 100644 --- a/builder_client.go +++ b/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 { @@ -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/buildfile.go b/buildfile.go index fb5c1c9d5c..5ea5607fc7 100644 --- a/buildfile.go +++ b/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,7 +266,7 @@ 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") @@ -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/buildfile_test.go b/buildfile_test.go index b6f4e62ae9..ffbcdbbddc 100644 --- a/buildfile_test.go +++ b/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/commands.go b/commands.go index 943b2198c1..f12e9bcb11 100644 --- a/commands.go +++ b/commands.go @@ -31,7 +31,7 @@ import ( const VERSION = "0.4.0" var ( - GIT_COMMIT string + GITCOMMIT string ) func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) { @@ -330,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 @@ -357,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 @@ -385,7 +385,7 @@ 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) @@ -418,7 +418,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error { return err } - var out ApiInfo + var out APIInfo if err := json.Unmarshal(body, &out); err != nil { return err } @@ -603,7 +603,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 @@ -612,7 +612,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 @@ -785,7 +785,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 @@ -807,16 +807,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)) } } } @@ -863,7 +863,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 @@ -876,15 +876,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)) } } } @@ -927,13 +927,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 } @@ -1070,7 +1070,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error { return err } - outs := []ApiSearch{} + outs := []APISearch{} err = json.Unmarshal(body, &outs) if err != nil { return err @@ -1202,7 +1202,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { return err } - out := &ApiRun{} + out := &APIRun{} err = json.Unmarshal(body, out) if err != nil { return err @@ -1223,18 +1223,18 @@ 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 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) }() } @@ -1252,7 +1252,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 @@ -1263,7 +1263,7 @@ func (cli *DockerCli) CmdRun(args ...string) error { } } if !config.AttachStdout && !config.AttachStderr { - fmt.Println(out.Id) + fmt.Println(out.ID) } return nil } @@ -1312,7 +1312,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 } @@ -1344,7 +1344,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 } @@ -1371,7 +1371,7 @@ 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 { @@ -1394,7 +1394,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 } diff --git a/container.go b/container.go index 9c28e5aa23..2e383c0d4b 100644 --- a/container.go +++ b/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 @@ -438,17 +438,17 @@ func (container *Container) Start() error { if err := os.MkdirAll(path.Join(container.RootfsPath(), volPath), 0755); err != nil { return nil } - container.Volumes[volPath] = c.Id + 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", @@ -582,8 +582,8 @@ func (container *Container) allocateNetwork() error { } 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,7 +597,7 @@ func (container *Container) releaseNetwork() { // FIXME: replace this with a control socket within docker-init func (container *Container) waitLxc() error { for { - output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput() + output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput() if err != nil { return err } @@ -615,12 +615,12 @@ 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") @@ -634,24 +634,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 @@ -672,7 +672,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) } } @@ -682,17 +682,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 } @@ -720,7 +720,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 { @@ -730,7 +730,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 } @@ -836,16 +836,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) { @@ -885,7 +885,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/container_test.go b/container_test.go index 117f0f3eb3..8ec1fa40ee 100644 --- a/container_test.go +++ b/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"}, }, ) @@ -221,7 +221,7 @@ func TestDiff(t *testing.T) { // Create a new containere container3, err := builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"rm", "/bin/httpd"}, }, ) @@ -260,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"}, }, ) @@ -291,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 { @@ -340,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"}, }, ) @@ -372,7 +372,7 @@ func TestCommitRun(t *testing.T) { container2, err := builder.Create( &Config{ - Image: img.Id, + Image: img.ID, Cmd: []string{"cat", "/world"}, }, ) @@ -419,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"}, @@ -463,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"}, }, ) @@ -491,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"}, }, ) @@ -515,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", }, @@ -563,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"}, }, ) @@ -611,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 { @@ -626,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 { @@ -648,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"}, }, ) @@ -681,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, @@ -763,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"}, }, ) @@ -781,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", @@ -801,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", @@ -821,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", @@ -843,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", @@ -872,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"}, }, ) @@ -882,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"}, }, ) @@ -928,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, @@ -975,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, @@ -1022,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"}, }, ) @@ -1100,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", @@ -1128,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"}, }, ) @@ -1163,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/contrib/crashTest.go b/contrib/crashTest.go index 320e97c52a..b3dbacaf03 100644 --- a/contrib/crashTest.go +++ b/contrib/crashTest.go @@ -11,13 +11,13 @@ import ( "time" ) -var DOCKER_PATH = 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/docker/docker.go b/docker/docker.go index 7b8aa7f858..dada16e11e 100644 --- a/docker/docker.go +++ b/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/graph.go b/graph.go index 7a819dce64..daa21f3053 100644 --- a/graph.go +++ b/graph.go @@ -86,14 +86,14 @@ func (graph *Graph) Get(name string) (*Image, error) { if err != nil { return nil, err } - if img.Id != id { - return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id) + if img.ID != id { + return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.ID) } img.graph = graph graph.lockSumMap.Lock() defer graph.lockSumMap.Unlock() - if _, exists := graph.checksumLock[img.Id]; !exists { - graph.checksumLock[img.Id] = &sync.Mutex{} + if _, exists := graph.checksumLock[img.ID]; !exists { + graph.checksumLock[img.ID] = &sync.Mutex{} } return img, nil } @@ -101,7 +101,7 @@ func (graph *Graph) Get(name string) (*Image, error) { // Create creates a new image and registers it in the graph. func (graph *Graph) Create(layerData Archive, container *Container, comment, author string, config *Config) (*Image, error) { img := &Image{ - Id: GenerateId(), + ID: GenerateID(), Comment: comment, Created: time.Now(), DockerVersion: VERSION, @@ -111,7 +111,7 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut } if container != nil { img.Parent = container.Image - img.Container = container.Id + img.Container = container.ID img.ContainerConfig = *container.Config } if err := graph.Register(layerData, layerData != nil, img); err != nil { @@ -124,12 +124,12 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut // Register imports a pre-existing image into the graph. // FIXME: pass img as first argument func (graph *Graph) Register(layerData Archive, store bool, img *Image) error { - if err := ValidateId(img.Id); err != nil { + if err := ValidateID(img.ID); err != nil { return err } // (This is a convenience to save time. Race conditions are taken care of by os.Rename) - if graph.Exists(img.Id) { - return fmt.Errorf("Image %s already exists", img.Id) + if graph.Exists(img.ID) { + return fmt.Errorf("Image %s already exists", img.ID) } tmp, err := graph.Mktemp("") defer os.RemoveAll(tmp) @@ -140,12 +140,12 @@ func (graph *Graph) Register(layerData Archive, store bool, img *Image) error { return err } // Commit - if err := os.Rename(tmp, graph.imageRoot(img.Id)); err != nil { + if err := os.Rename(tmp, graph.imageRoot(img.ID)); err != nil { return err } img.graph = graph - graph.idIndex.Add(img.Id) - graph.checksumLock[img.Id] = &sync.Mutex{} + graph.idIndex.Add(img.ID) + graph.checksumLock[img.ID] = &sync.Mutex{} return nil } @@ -173,7 +173,7 @@ func (graph *Graph) TempLayerArchive(id string, compression Compression, output // Mktemp creates a temporary sub-directory inside the graph's filesystem. func (graph *Graph) Mktemp(id string) (string, error) { if id == "" { - id = GenerateId() + id = GenerateID() } tmp, err := graph.tmp() if err != nil { @@ -230,7 +230,7 @@ func (graph *Graph) Map() (map[string]*Image, error) { } images := make(map[string]*Image, len(all)) for _, image := range all { - images[image.Id] = image + images[image.ID] = image } return images, nil } @@ -273,10 +273,10 @@ func (graph *Graph) ByParent() (map[string][]*Image, error) { if err != nil { return } - if children, exists := byParent[parent.Id]; exists { - byParent[parent.Id] = []*Image{image} + if children, exists := byParent[parent.ID]; exists { + byParent[parent.ID] = []*Image{image} } else { - byParent[parent.Id] = append(children, image) + byParent[parent.ID] = append(children, image) } }) return byParent, err @@ -293,8 +293,8 @@ func (graph *Graph) Heads() (map[string]*Image, error) { err = graph.WalkAll(func(image *Image) { // If it's not in the byParent lookup table, then // it's not a parent -> so it's a head! - if _, exists := byParent[image.Id]; !exists { - heads[image.Id] = image + if _, exists := byParent[image.ID]; !exists { + heads[image.ID] = image } }) return heads, err @@ -317,11 +317,11 @@ func (graph *Graph) getStoredChecksums() (map[string]string, error) { } func (graph *Graph) storeChecksums(checksums map[string]string) error { - checksumJson, err := json.Marshal(checksums) + checksumJSON, err := json.Marshal(checksums) if err != nil { return err } - if err := ioutil.WriteFile(path.Join(graph.Root, "checksums"), checksumJson, 0600); err != nil { + if err := ioutil.WriteFile(path.Join(graph.Root, "checksums"), checksumJSON, 0600); err != nil { return err } return nil diff --git a/graph_test.go b/graph_test.go index 7c1e5c0978..8dedb96669 100644 --- a/graph_test.go +++ b/graph_test.go @@ -34,14 +34,14 @@ func TestInterruptedRegister(t *testing.T) { defer os.RemoveAll(graph.Root) badArchive, w := io.Pipe() // Use a pipe reader as a fake archive which never yields data image := &Image{ - Id: GenerateId(), + ID: GenerateID(), Comment: "testing", Created: time.Now(), } go graph.Register(badArchive, false, image) time.Sleep(200 * time.Millisecond) w.CloseWithError(errors.New("But I'm not a tarball!")) // (Nobody's perfect, darling) - if _, err := graph.Get(image.Id); err == nil { + if _, err := graph.Get(image.ID); err == nil { t.Fatal("Image should not exist after Register is interrupted") } // Registering the same image again should succeed if the first register was interrupted @@ -67,7 +67,7 @@ func TestGraphCreate(t *testing.T) { if err != nil { t.Fatal(err) } - if err := ValidateId(image.Id); err != nil { + if err := ValidateID(image.ID); err != nil { t.Fatal(err) } if image.Comment != "Testing" { @@ -91,7 +91,7 @@ func TestRegister(t *testing.T) { t.Fatal(err) } image := &Image{ - Id: GenerateId(), + ID: GenerateID(), Comment: "testing", Created: time.Now(), } @@ -104,11 +104,11 @@ func TestRegister(t *testing.T) { } else if l := len(images); l != 1 { t.Fatalf("Wrong number of images. Should be %d, not %d", 1, l) } - if resultImg, err := graph.Get(image.Id); err != nil { + if resultImg, err := graph.Get(image.ID); err != nil { t.Fatal(err) } else { - if resultImg.Id != image.Id { - t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.Id, resultImg.Id) + if resultImg.ID != image.ID { + t.Fatalf("Wrong image ID. Should be '%s', not '%s'", image.ID, resultImg.ID) } if resultImg.Comment != image.Comment { t.Fatalf("Wrong image comment. Should be '%s', not '%s'", image.Comment, resultImg.Comment) @@ -156,7 +156,7 @@ func TestDeletePrefix(t *testing.T) { graph := tempGraph(t) defer os.RemoveAll(graph.Root) img := createTestImage(graph, t) - if err := graph.Delete(utils.TruncateId(img.Id)); err != nil { + if err := graph.Delete(utils.TruncateID(img.ID)); err != nil { t.Fatal(err) } assertNImages(graph, t, 0) @@ -187,7 +187,7 @@ func TestDelete(t *testing.T) { t.Fatal(err) } assertNImages(graph, t, 1) - if err := graph.Delete(img.Id); err != nil { + if err := graph.Delete(img.ID); err != nil { t.Fatal(err) } assertNImages(graph, t, 0) @@ -201,7 +201,7 @@ func TestDelete(t *testing.T) { t.Fatal(err) } assertNImages(graph, t, 2) - if err := graph.Delete(img1.Id); err != nil { + if err := graph.Delete(img1.ID); err != nil { t.Fatal(err) } assertNImages(graph, t, 1) @@ -216,7 +216,7 @@ func TestDelete(t *testing.T) { if err := graph.Register(archive, false, img1); err != nil { t.Fatal(err) } - if err := graph.Delete(img1.Id); err != nil { + if err := graph.Delete(img1.ID); err != nil { t.Fatal(err) } assertNImages(graph, t, 1) diff --git a/image.go b/image.go index 3617d7dd19..7a98ef41a1 100644 --- a/image.go +++ b/image.go @@ -18,7 +18,7 @@ import ( ) type Image struct { - Id string `json:"id"` + ID string `json:"id"` Parent string `json:"parent,omitempty"` Comment string `json:"comment,omitempty"` Created time.Time `json:"created"` @@ -42,17 +42,17 @@ func LoadImage(root string) (*Image, error) { if err := json.Unmarshal(jsonData, img); err != nil { return nil, err } - if err := ValidateId(img.Id); err != nil { + if err := ValidateID(img.ID); err != nil { return nil, err } // Check that the filesystem layer exists if stat, err := os.Stat(layerPath(root)); err != nil { if os.IsNotExist(err) { - return nil, fmt.Errorf("Couldn't load image %s: no filesystem layer", img.Id) + return nil, fmt.Errorf("Couldn't load image %s: no filesystem layer", img.ID) } return nil, err } else if !stat.IsDir() { - return nil, fmt.Errorf("Couldn't load image %s: %s is not a directory", img.Id, layerPath(root)) + return nil, fmt.Errorf("Couldn't load image %s: %s is not a directory", img.ID, layerPath(root)) } return img, nil } @@ -60,7 +60,7 @@ func LoadImage(root string) (*Image, error) { func StoreImage(img *Image, layerData Archive, root string, store bool) error { // Check that root doesn't already exist if _, err := os.Stat(root); err == nil { - return fmt.Errorf("Image %s already exists", img.Id) + return fmt.Errorf("Image %s already exists", img.ID) } else if !os.IsNotExist(err) { return err } @@ -180,11 +180,11 @@ func (image *Image) Changes(rw string) ([]Change, error) { return Changes(layers, rw) } -func (image *Image) ShortId() string { - return utils.TruncateId(image.Id) +func (image *Image) ShortID() string { + return utils.TruncateID(image.ID) } -func ValidateId(id string) error { +func ValidateID(id string) error { if id == "" { return fmt.Errorf("Image id can't be empty") } @@ -194,7 +194,7 @@ func ValidateId(id string) error { return nil } -func GenerateId() string { +func GenerateID() string { id := make([]byte, 32) _, err := io.ReadFull(rand.Reader, id) if err != nil { @@ -240,7 +240,7 @@ func (img *Image) layers() ([]string, error) { return nil, e } if len(list) == 0 { - return nil, fmt.Errorf("No layer found for image %s\n", img.Id) + return nil, fmt.Errorf("No layer found for image %s\n", img.ID) } return list, nil } @@ -275,7 +275,7 @@ func (img *Image) root() (string, error) { if img.graph == nil { return "", fmt.Errorf("Can't lookup root of unregistered image") } - return img.graph.imageRoot(img.Id), nil + return img.graph.imageRoot(img.ID), nil } // Return the path of an image's layer @@ -288,8 +288,8 @@ func (img *Image) layer() (string, error) { } func (img *Image) Checksum() (string, error) { - img.graph.checksumLock[img.Id].Lock() - defer img.graph.checksumLock[img.Id].Unlock() + img.graph.checksumLock[img.ID].Lock() + defer img.graph.checksumLock[img.ID].Unlock() root, err := img.root() if err != nil { @@ -300,7 +300,7 @@ func (img *Image) Checksum() (string, error) { if err != nil { return "", err } - if checksum, ok := checksums[img.Id]; ok { + if checksum, ok := checksums[img.ID]; ok { return checksum, nil } @@ -351,7 +351,7 @@ func (img *Image) Checksum() (string, error) { return "", err } - checksums[img.Id] = hash + checksums[img.ID] = hash // Dump the checksums to disc if err := img.graph.storeChecksums(checksums); err != nil { @@ -362,7 +362,7 @@ func (img *Image) Checksum() (string, error) { } // Build an Image object from raw json data -func NewImgJson(src []byte) (*Image, error) { +func NewImgJSON(src []byte) (*Image, error) { ret := &Image{} utils.Debugf("Json string: {%s}\n", src) diff --git a/lxc_template.go b/lxc_template.go index 008a717bad..3d102a5a2e 100644 --- a/lxc_template.go +++ b/lxc_template.go @@ -19,7 +19,7 @@ lxc.network.flags = up lxc.network.link = {{.NetworkSettings.Bridge}} lxc.network.name = eth0 lxc.network.mtu = 1500 -lxc.network.ipv4 = {{.NetworkSettings.IpAddress}}/{{.NetworkSettings.IpPrefixLen}} +lxc.network.ipv4 = {{.NetworkSettings.IPAddress}}/{{.NetworkSettings.IPPrefixLen}} # root filesystem {{$ROOTFS := .RootfsPath}} diff --git a/network.go b/network.go index 2bdb4862ce..f78e320fd2 100644 --- a/network.go +++ b/network.go @@ -52,7 +52,7 @@ func ipToInt(ip net.IP) int32 { } // Converts 32 bit integer into a 4 bytes IP address -func intToIp(n int32) net.IP { +func intToIP(n int32) net.IP { b := make([]byte, 4) binary.BigEndian.PutUint32(b, uint32(n)) return net.IP(b) @@ -396,7 +396,7 @@ func (alloc *IPAllocator) run() { } } - ip := allocatedIP{ip: intToIp(newNum)} + ip := allocatedIP{ip: intToIP(newNum)} if inUse { ip.err = errors.New("No unallocated IP available") } diff --git a/network_test.go b/network_test.go index 8bae9e3c32..df19a73d74 100644 --- a/network_test.go +++ b/network_test.go @@ -137,7 +137,7 @@ func TestConversion(t *testing.T) { if i == 0 { t.Fatal("converted to zero") } - conv := intToIp(i) + conv := intToIP(i) if !ip.Equal(conv) { t.Error(conv.String()) } diff --git a/registry/registry.go b/registry/registry.go index b6cda92841..befceb8e27 100644 --- a/registry/registry.go +++ b/registry/registry.go @@ -107,8 +107,8 @@ func (r *Registry) getImagesInRepository(repository string, authConfig *auth.Aut // Retrieve an image from the Registry. // Returns the Image object as well as the layer as an Archive (io.Reader) -func (r *Registry) GetRemoteImageJson(imgId, registry string, token []string) ([]byte, error) { - // Get the Json +func (r *Registry) GetRemoteImageJSON(imgId, registry string, token []string) ([]byte, error) { + // Get the JSON req, err := http.NewRequest("GET", registry+"/images/"+imgId+"/json", nil) if err != nil { return nil, fmt.Errorf("Failed to download json: %s", err) @@ -169,11 +169,11 @@ func (r *Registry) GetRemoteTags(registries []string, repository string, token [ } result := make(map[string]string) - rawJson, err := ioutil.ReadAll(res.Body) + rawJSON, err := ioutil.ReadAll(res.Body) if err != nil { return nil, err } - if err := json.Unmarshal(rawJson, &result); err != nil { + if err := json.Unmarshal(rawJSON, &result); err != nil { return nil, err } return result, nil @@ -219,19 +219,19 @@ func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) { return nil, fmt.Errorf("Index response didn't contain any endpoints") } - checksumsJson, err := ioutil.ReadAll(res.Body) + checksumsJSON, err := ioutil.ReadAll(res.Body) if err != nil { return nil, err } remoteChecksums := []*ImgData{} - if err := json.Unmarshal(checksumsJson, &remoteChecksums); err != nil { + if err := json.Unmarshal(checksumsJSON, &remoteChecksums); err != nil { return nil, err } // Forge a better object from the retrieved data imgsData := make(map[string]*ImgData) for _, elem := range remoteChecksums { - imgsData[elem.Id] = elem + imgsData[elem.ID] = elem } return &RepositoryData{ @@ -242,10 +242,10 @@ func (r *Registry) GetRepositoryData(remote string) (*RepositoryData, error) { } // Push a local image to the registry -func (r *Registry) PushImageJsonRegistry(imgData *ImgData, jsonRaw []byte, registry string, token []string) error { +func (r *Registry) PushImageJSONRegistry(imgData *ImgData, jsonRaw []byte, registry string, token []string) error { registry = "https://" + registry + "/v1" // FIXME: try json with UTF8 - req, err := http.NewRequest("PUT", registry+"/images/"+imgData.Id+"/json", strings.NewReader(string(jsonRaw))) + req, err := http.NewRequest("PUT", registry+"/images/"+imgData.ID+"/json", strings.NewReader(string(jsonRaw))) if err != nil { return err } @@ -253,7 +253,7 @@ func (r *Registry) PushImageJsonRegistry(imgData *ImgData, jsonRaw []byte, regis req.Header.Set("Authorization", "Token "+strings.Join(token, ",")) req.Header.Set("X-Docker-Checksum", imgData.Checksum) - utils.Debugf("Setting checksum for %s: %s", imgData.Id, imgData.Checksum) + utils.Debugf("Setting checksum for %s: %s", imgData.ID, imgData.Checksum) res, err := doWithCookies(r.client, req) if err != nil { return fmt.Errorf("Failed to upload metadata: %s", err) @@ -328,8 +328,8 @@ func (r *Registry) PushRegistryTag(remote, revision, tag, registry string, token return nil } -func (r *Registry) PushImageJsonIndex(remote string, imgList []*ImgData, validate bool) (*RepositoryData, error) { - imgListJson, err := json.Marshal(imgList) +func (r *Registry) PushImageJSONIndex(remote string, imgList []*ImgData, validate bool) (*RepositoryData, error) { + imgListJSON, err := json.Marshal(imgList) if err != nil { return nil, err } @@ -338,14 +338,14 @@ func (r *Registry) PushImageJsonIndex(remote string, imgList []*ImgData, validat suffix = "images" } - utils.Debugf("Image list pushed to index:\n%s\n", imgListJson) + utils.Debugf("Image list pushed to index:\n%s\n", imgListJSON) - req, err := http.NewRequest("PUT", auth.IndexServerAddress()+"/repositories/"+remote+"/"+suffix, bytes.NewReader(imgListJson)) + req, err := http.NewRequest("PUT", auth.IndexServerAddress()+"/repositories/"+remote+"/"+suffix, bytes.NewReader(imgListJSON)) if err != nil { return nil, err } req.SetBasicAuth(r.authConfig.Username, r.authConfig.Password) - req.ContentLength = int64(len(imgListJson)) + req.ContentLength = int64(len(imgListJSON)) req.Header.Set("X-Docker-Token", "true") res, err := r.client.Do(req) @@ -357,12 +357,12 @@ func (r *Registry) PushImageJsonIndex(remote string, imgList []*ImgData, validat // Redirect if necessary for res.StatusCode >= 300 && res.StatusCode < 400 { utils.Debugf("Redirected to %s\n", res.Header.Get("Location")) - req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJson)) + req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJSON)) if err != nil { return nil, err } req.SetBasicAuth(r.authConfig.Username, r.authConfig.Password) - req.ContentLength = int64(len(imgListJson)) + req.ContentLength = int64(len(imgListJSON)) req.Header.Set("X-Docker-Token", "true") res, err = r.client.Do(req) @@ -463,7 +463,7 @@ type RepositoryData struct { } type ImgData struct { - Id string `json:"id"` + ID string `json:"id"` Checksum string `json:"checksum,omitempty"` Tag string `json:",omitempty"` } diff --git a/runtime.go b/runtime.go index ad1852e902..1c22bd085c 100644 --- a/runtime.go +++ b/runtime.go @@ -51,7 +51,7 @@ func (runtime *Runtime) List() []*Container { func (runtime *Runtime) getContainerElement(id string) *list.Element { for e := runtime.containers.Front(); e != nil; e = e.Next() { container := e.Value.(*Container) - if container.Id == id { + if container.ID == id { return e } } @@ -83,8 +83,8 @@ func (runtime *Runtime) Load(id string) (*Container, error) { if err := container.FromDisk(); err != nil { return nil, err } - if container.Id != id { - return container, fmt.Errorf("Container %s is stored at %s", container.Id, id) + if container.ID != id { + return container, fmt.Errorf("Container %s is stored at %s", container.ID, id) } if container.State.Running { container.State.Ghost = true @@ -95,12 +95,12 @@ func (runtime *Runtime) Load(id string) (*Container, error) { return container, nil } -// Register makes a container object usable by the runtime as +// Register makes a container object usable by the runtime as func (runtime *Runtime) Register(container *Container) error { - if container.runtime != nil || runtime.Exists(container.Id) { + if container.runtime != nil || runtime.Exists(container.ID) { return fmt.Errorf("Container is already loaded") } - if err := validateId(container.Id); err != nil { + if err := validateID(container.ID); err != nil { return err } @@ -123,7 +123,7 @@ func (runtime *Runtime) Register(container *Container) error { } // done runtime.containers.PushBack(container) - runtime.idIndex.Add(container.Id) + runtime.idIndex.Add(container.ID) // When we actually restart, Start() do the monitoring. // However, when we simply 'reattach', we have to restart a monitor @@ -133,12 +133,12 @@ func (runtime *Runtime) Register(container *Container) error { // if so, then we need to restart monitor and init a new lock // If the container is supposed to be running, make sure of it if container.State.Running { - output, err := exec.Command("lxc-info", "-n", container.Id).CombinedOutput() + output, err := exec.Command("lxc-info", "-n", container.ID).CombinedOutput() if err != nil { return err } if !strings.Contains(string(output), "RUNNING") { - utils.Debugf("Container %s was supposed to be running be is not.", container.Id) + utils.Debugf("Container %s was supposed to be running be is not.", container.ID) if runtime.autoRestart { utils.Debugf("Restarting") container.State.Ghost = false @@ -182,9 +182,9 @@ func (runtime *Runtime) Destroy(container *Container) error { return fmt.Errorf("The given container is ") } - element := runtime.getContainerElement(container.Id) + element := runtime.getContainerElement(container.ID) if element == nil { - return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.Id) + return fmt.Errorf("Container %v not found - maybe it was already destroyed?", container.ID) } if err := container.Stop(3); err != nil { @@ -194,14 +194,14 @@ func (runtime *Runtime) Destroy(container *Container) error { return err } else if mounted { if err := container.Unmount(); err != nil { - return fmt.Errorf("Unable to unmount container %v: %v", container.Id, err) + return fmt.Errorf("Unable to unmount container %v: %v", container.ID, err) } } // Deregister the container before removing its directory, to avoid race conditions - runtime.idIndex.Delete(container.Id) + runtime.idIndex.Delete(container.ID) runtime.containers.Remove(element) if err := os.RemoveAll(container.root); err != nil { - return fmt.Errorf("Unable to remove filesystem for %v: %v", container.Id, err) + return fmt.Errorf("Unable to remove filesystem for %v: %v", container.ID, err) } return nil } @@ -218,7 +218,7 @@ func (runtime *Runtime) restore() error { utils.Debugf("Failed to load container %v: %v", id, err) continue } - utils.Debugf("Loaded container %v", container.Id) + utils.Debugf("Loaded container %v", container.ID) } return nil } diff --git a/runtime_test.go b/runtime_test.go index 1190510279..642c8a0ce6 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -120,7 +120,7 @@ func TestRuntimeCreate(t *testing.T) { builder := NewBuilder(runtime) container, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -140,29 +140,29 @@ func TestRuntimeCreate(t *testing.T) { } // Make sure the container List() returns is the right one - if runtime.List()[0].Id != container.Id { + if runtime.List()[0].ID != container.ID { t.Errorf("Unexpected container %v returned by List", runtime.List()[0]) } // Make sure we can get the container with Get() - if runtime.Get(container.Id) == nil { + if runtime.Get(container.ID) == nil { t.Errorf("Unable to get newly created container") } // Make sure it is the right container - if runtime.Get(container.Id) != container { + if runtime.Get(container.ID) != container { t.Errorf("Get() returned the wrong container") } // Make sure Exists returns it as existing - if !runtime.Exists(container.Id) { + if !runtime.Exists(container.ID) { t.Errorf("Exists() returned false for a newly created container") } // Make sure crete with bad parameters returns an error _, err = builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, }, ) if err == nil { @@ -171,7 +171,7 @@ func TestRuntimeCreate(t *testing.T) { _, err = builder.Create( &Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{}, }, ) @@ -187,7 +187,7 @@ func TestDestroy(t *testing.T) { } defer nuke(runtime) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -210,7 +210,7 @@ func TestDestroy(t *testing.T) { } // Make sure runtime.Get() refuses to return the unexisting container - if runtime.Get(container.Id) != nil { + if runtime.Get(container.ID) != nil { t.Errorf("Unable to get newly created container") } @@ -237,7 +237,7 @@ func TestGet(t *testing.T) { builder := NewBuilder(runtime) container1, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -247,7 +247,7 @@ func TestGet(t *testing.T) { defer runtime.Destroy(container1) container2, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -257,7 +257,7 @@ func TestGet(t *testing.T) { defer runtime.Destroy(container2) container3, err := builder.Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -266,16 +266,16 @@ func TestGet(t *testing.T) { } defer runtime.Destroy(container3) - if runtime.Get(container1.Id) != container1 { - t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.Id), container1) + if runtime.Get(container1.ID) != container1 { + t.Errorf("Get(test1) returned %v while expecting %v", runtime.Get(container1.ID), container1) } - if runtime.Get(container2.Id) != container2 { - t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.Id), container2) + if runtime.Get(container2.ID) != container2 { + t.Errorf("Get(test2) returned %v while expecting %v", runtime.Get(container2.ID), container2) } - if runtime.Get(container3.Id) != container3 { - t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.Id), container3) + if runtime.Get(container3.ID) != container3 { + t.Errorf("Get(test3) returned %v while expecting %v", runtime.Get(container3.ID), container3) } } @@ -283,7 +283,7 @@ func TestGet(t *testing.T) { func findAvailalblePort(runtime *Runtime, port int) (*Container, error) { strPort := strconv.Itoa(port) container, err := NewBuilder(runtime).Create(&Config{ - Image: GetTestImage(runtime).Id, + Image: GetTestImage(runtime).ID, Cmd: []string{"sh", "-c", "echo well hello there | nc -l -p " + strPort}, PortSpecs: []string{strPort}, }, @@ -379,7 +379,7 @@ func TestRestore(t *testing.T) { // Create a container with one instance of docker container1, err := builder.Create(&Config{ - Image: GetTestImage(runtime1).Id, + Image: GetTestImage(runtime1).ID, Cmd: []string{"ls", "-al"}, }, ) @@ -390,7 +390,7 @@ func TestRestore(t *testing.T) { // Create a second container meant to be killed container2, err := builder.Create(&Config{ - Image: GetTestImage(runtime1).Id, + Image: GetTestImage(runtime1).ID, Cmd: []string{"/bin/cat"}, OpenStdin: true, }, @@ -406,7 +406,7 @@ func TestRestore(t *testing.T) { } if !container2.State.Running { - t.Fatalf("Container %v should appear as running but isn't", container2.Id) + t.Fatalf("Container %v should appear as running but isn't", container2.ID) } // Simulate a crash/manual quit of dockerd: process dies, states stays 'Running' @@ -426,7 +426,7 @@ func TestRestore(t *testing.T) { } if !container2.State.Running { - t.Fatalf("Container %v should appear as running but isn't", container2.Id) + t.Fatalf("Container %v should appear as running but isn't", container2.ID) } // Here are are simulating a docker restart - that is, reloading all containers @@ -442,14 +442,14 @@ func TestRestore(t *testing.T) { runningCount := 0 for _, c := range runtime2.List() { if c.State.Running { - t.Errorf("Running container found: %v (%v)", c.Id, c.Path) + t.Errorf("Running container found: %v (%v)", c.ID, c.Path) runningCount++ } } if runningCount != 0 { t.Fatalf("Expected 0 container alive, %d found", runningCount) } - container3 := runtime2.Get(container1.Id) + container3 := runtime2.Get(container1.ID) if container3 == nil { t.Fatal("Unable to Get container") } diff --git a/server.go b/server.go index 9e98b87c21..3287bf9616 100644 --- a/server.go +++ b/server.go @@ -16,10 +16,10 @@ import ( "strings" ) -func (srv *Server) DockerVersion() ApiVersion { - return ApiVersion{ +func (srv *Server) DockerVersion() APIVersion { + return APIVersion{ Version: VERSION, - GitCommit: GIT_COMMIT, + GitCommit: GITCOMMIT, GoVersion: runtime.Version(), } } @@ -52,16 +52,16 @@ func (srv *Server) ContainerExport(name string, out io.Writer) error { return fmt.Errorf("No such container: %s", name) } -func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) { +func (srv *Server) ImagesSearch(term string) ([]APISearch, error) { results, err := registry.NewRegistry(srv.runtime.root).SearchRepositories(term) if err != nil { return nil, err } - var outs []ApiSearch + var outs []APISearch for _, repo := range results.Results { - var out ApiSearch + var out APISearch out.Description = repo["description"] if len(out.Description) > 45 { out.Description = utils.Trunc(out.Description, 42) + "..." @@ -85,7 +85,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils. } defer file.Body.Close() - config, _, err := ParseRun([]string{img.Id, "echo", "insert", url, path}, srv.runtime.capabilities) + config, _, err := ParseRun([]string{img.ID, "echo", "insert", url, path}, srv.runtime.capabilities) if err != nil { return "", err } @@ -104,8 +104,8 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer, sf *utils. if err != nil { return "", err } - out.Write(sf.FormatStatus(img.Id)) - return img.ShortId(), nil + out.Write(sf.FormatStatus(img.ID)) + return img.ShortID(), nil } func (srv *Server) ImagesViz(out io.Writer) error { @@ -125,9 +125,9 @@ func (srv *Server) ImagesViz(out io.Writer) error { return fmt.Errorf("Error while getting parent image: %v", err) } if parentImage != nil { - out.Write([]byte(" \"" + parentImage.ShortId() + "\" -> \"" + image.ShortId() + "\"\n")) + out.Write([]byte(" \"" + parentImage.ShortID() + "\" -> \"" + image.ShortID() + "\"\n")) } else { - out.Write([]byte(" base -> \"" + image.ShortId() + "\" [style=invis]\n")) + out.Write([]byte(" base -> \"" + image.ShortID() + "\" [style=invis]\n")) } } @@ -135,7 +135,7 @@ func (srv *Server) ImagesViz(out io.Writer) error { for name, repository := range srv.runtime.repositories.Repositories { for tag, id := range repository { - reporefs[utils.TruncateId(id)] = append(reporefs[utils.TruncateId(id)], fmt.Sprintf("%s:%s", name, tag)) + reporefs[utils.TruncateID(id)] = append(reporefs[utils.TruncateID(id)], fmt.Sprintf("%s:%s", name, tag)) } } @@ -146,7 +146,7 @@ func (srv *Server) ImagesViz(out io.Writer) error { return nil } -func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { +func (srv *Server) Images(all bool, filter string) ([]APIImages, error) { var ( allImages map[string]*Image err error @@ -159,13 +159,13 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { if err != nil { return nil, err } - outs := []ApiImages{} //produce [] when empty instead of 'null' + outs := []APIImages{} //produce [] when empty instead of 'null' for name, repository := range srv.runtime.repositories.Repositories { if filter != "" && name != filter { continue } for tag, id := range repository { - var out ApiImages + var out APIImages image, err := srv.runtime.graph.Get(id) if err != nil { log.Printf("Warning: couldn't load %s from %s/%s: %s", id, name, tag, err) @@ -174,7 +174,7 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { delete(allImages, id) out.Repository = name out.Tag = tag - out.Id = image.Id + out.ID = image.ID out.Created = image.Created.Unix() outs = append(outs, out) } @@ -182,8 +182,8 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { // Display images which aren't part of a if filter == "" { for _, image := range allImages { - var out ApiImages - out.Id = image.Id + var out APIImages + out.ID = image.ID out.Created = image.Created.Unix() outs = append(outs, out) } @@ -191,7 +191,7 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { return outs, nil } -func (srv *Server) DockerInfo() *ApiInfo { +func (srv *Server) DockerInfo() *APIInfo { images, _ := srv.runtime.graph.All() var imgcount int if images == nil { @@ -199,7 +199,7 @@ func (srv *Server) DockerInfo() *ApiInfo { } else { imgcount = len(images) } - return &ApiInfo{ + return &APIInfo{ Containers: len(srv.runtime.List()), Images: imgcount, MemoryLimit: srv.runtime.capabilities.MemoryLimit, @@ -210,16 +210,16 @@ func (srv *Server) DockerInfo() *ApiInfo { } } -func (srv *Server) ImageHistory(name string) ([]ApiHistory, error) { +func (srv *Server) ImageHistory(name string) ([]APIHistory, error) { image, err := srv.runtime.repositories.LookupImage(name) if err != nil { return nil, err } - outs := []ApiHistory{} //produce [] when empty instead of 'null' + outs := []APIHistory{} //produce [] when empty instead of 'null' err = image.WalkHistory(func(img *Image) error { - var out ApiHistory - out.Id = srv.runtime.repositories.ImageName(img.ShortId()) + var out APIHistory + out.ID = srv.runtime.repositories.ImageName(img.ShortID()) out.Created = img.Created.Unix() out.CreatedBy = strings.Join(img.ContainerConfig.Cmd, " ") outs = append(outs, out) @@ -236,17 +236,17 @@ func (srv *Server) ContainerChanges(name string) ([]Change, error) { return nil, fmt.Errorf("No such container: %s", name) } -func (srv *Server) Containers(all bool, n int, since, before string) []ApiContainers { +func (srv *Server) Containers(all bool, n int, since, before string) []APIContainers { var foundBefore bool var displayed int - retContainers := []ApiContainers{} + retContainers := []APIContainers{} for _, container := range srv.runtime.List() { if !container.State.Running && !all && n == -1 && since == "" && before == "" { continue } if before != "" { - if container.ShortId() == before { + if container.ShortID() == before { foundBefore = true continue } @@ -257,13 +257,13 @@ func (srv *Server) Containers(all bool, n int, since, before string) []ApiContai if displayed == n { break } - if container.ShortId() == since { + if container.ShortID() == since { break } displayed++ - c := ApiContainers{ - Id: container.Id, + c := APIContainers{ + ID: container.ID, } c.Image = srv.runtime.repositories.ImageName(container.Image) c.Command = fmt.Sprintf("%s %s", container.Path, strings.Join(container.Args, " ")) @@ -284,7 +284,7 @@ func (srv *Server) ContainerCommit(name, repo, tag, author, comment string, conf if err != nil { return "", err } - return img.ShortId(), err + return img.ShortID(), err } func (srv *Server) ContainerTag(name, repo, tag string, force bool) error { @@ -305,19 +305,19 @@ func (srv *Server) pullImage(r *registry.Registry, out io.Writer, imgId, endpoin for _, id := range history { if !srv.runtime.graph.Exists(id) { out.Write(sf.FormatStatus("Pulling %s metadata", id)) - imgJson, err := r.GetRemoteImageJson(id, endpoint, token) + imgJSON, err := r.GetRemoteImageJSON(id, endpoint, token) if err != nil { // FIXME: Keep goging in case of error? return err } - img, err := NewImgJson(imgJson) + img, err := NewImgJSON(imgJSON) if err != nil { return fmt.Errorf("Failed to parse json: %s", err) } // Get the layer out.Write(sf.FormatStatus("Pulling %s fs layer", id)) - layer, contentLength, err := r.GetRemoteImageLayer(img.Id, endpoint, token) + layer, contentLength, err := r.GetRemoteImageLayer(img.ID, endpoint, token) if err != nil { return err } @@ -365,13 +365,13 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, a for _, img := range repoData.ImgList { if askedTag != "" && img.Tag != askedTag { - utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.Id) + utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID) continue } - out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.Id, img.Tag, remote)) + out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.ID, img.Tag, remote)) success := false for _, ep := range repoData.Endpoints { - if err := srv.pullImage(r, out, img.Id, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil { + if err := srv.pullImage(r, out, img.ID, "https://"+ep+"/v1", repoData.Tokens, sf); err != nil { out.Write(sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint", askedTag, err)) continue } @@ -461,16 +461,16 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]*registry.ImgDat return nil, err } img.WalkHistory(func(img *Image) error { - if _, exists := imageSet[img.Id]; exists { + if _, exists := imageSet[img.ID]; exists { return nil } - imageSet[img.Id] = struct{}{} - checksum, err := srv.getChecksum(img.Id) + imageSet[img.ID] = struct{}{} + checksum, err := srv.getChecksum(img.ID) if err != nil { return err } imgList = append([]*registry.ImgData{{ - Id: img.Id, + ID: img.ID, Checksum: checksum, Tag: tag, }}, imgList...) @@ -489,7 +489,7 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name stri } out.Write(sf.FormatStatus("Sending image list")) - repoData, err := r.PushImageJsonIndex(name, imgList, false) + repoData, err := r.PushImageJSONIndex(name, imgList, false) if err != nil { return err } @@ -498,22 +498,22 @@ func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name stri out.Write(sf.FormatStatus("Pushing repository %s to %s (%d tags)", name, ep, len(localRepo))) // For each image within the repo, push them for _, elem := range imgList { - if _, exists := repoData.ImgList[elem.Id]; exists { + if _, exists := repoData.ImgList[elem.ID]; exists { out.Write(sf.FormatStatus("Image %s already on registry, skipping", name)) continue } - if err := srv.pushImage(r, out, name, elem.Id, ep, repoData.Tokens, sf); err != nil { + if err := srv.pushImage(r, out, name, elem.ID, ep, repoData.Tokens, sf); err != nil { // FIXME: Continue on error? return err } - out.Write(sf.FormatStatus("Pushing tags for rev [%s] on {%s}", elem.Id, ep+"/users/"+name+"/"+elem.Tag)) - if err := r.PushRegistryTag(name, elem.Id, elem.Tag, ep, repoData.Tokens); err != nil { + out.Write(sf.FormatStatus("Pushing tags for rev [%s] on {%s}", elem.ID, ep+"/users/"+name+"/"+elem.Tag)) + if err := r.PushRegistryTag(name, elem.ID, elem.Tag, ep, repoData.Tokens); err != nil { return err } } } - if _, err := r.PushImageJsonIndex(name, imgList, true); err != nil { + if _, err := r.PushImageJSONIndex(name, imgList, true); err != nil { return err } return nil @@ -533,14 +533,14 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, return err } imgData := ®istry.ImgData{ - Id: imgId, + ID: imgId, Checksum: checksum, } // Send the json - if err := r.PushImageJsonRegistry(imgData, jsonRaw, ep, token); err != nil { + if err := r.PushImageJSONRegistry(imgData, jsonRaw, ep, token); err != nil { if err == registry.ErrAlreadyExists { - out.Write(sf.FormatStatus("Image %s already uploaded ; skipping", imgData.Id)) + out.Write(sf.FormatStatus("Image %s already uploaded ; skipping", imgData.ID)) return nil } return err @@ -573,7 +573,7 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, } // Send the layer - if err := r.PushImageLayerRegistry(imgData.Id, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("", "%v/%v (%v)"), sf), ep, token); err != nil { + if err := r.PushImageLayerRegistry(imgData.ID, utils.ProgressReader(layerData, int(layerData.Size), out, sf.FormatProgress("", "%v/%v (%v)"), sf), ep, token); err != nil { return err } return nil @@ -597,7 +597,7 @@ func (srv *Server) ImagePush(name, endpoint string, out io.Writer, sf *utils.Str return err } out.Write(sf.FormatStatus("The push refers to an image: [%s]", name)) - if err := srv.pushImage(r, out, name, img.Id, endpoint, nil, sf); err != nil { + if err := srv.pushImage(r, out, name, img.ID, endpoint, nil, sf); err != nil { return err } return nil @@ -634,11 +634,11 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write } // Optionally register the image at REPO/TAG if repo != "" { - if err := srv.runtime.repositories.Set(repo, tag, img.Id, true); err != nil { + if err := srv.runtime.repositories.Set(repo, tag, img.ID, true); err != nil { return err } } - out.Write(sf.FormatStatus(img.ShortId())) + out.Write(sf.FormatStatus(img.ShortID())) return nil } @@ -659,7 +659,7 @@ func (srv *Server) ContainerCreate(config *Config) (string, error) { } return "", err } - return container.ShortId(), nil + return container.ShortID(), nil } func (srv *Server) ContainerRestart(name string, t int) error { @@ -696,7 +696,7 @@ func (srv *Server) ContainerDestroy(name string, removeVolume bool) error { for volumeId := range volumes { // If the requested volu if c, exists := usedVolumes[volumeId]; exists { - log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.Id) + log.Printf("The volume %s is used by the container %s. Impossible to remove it. Skipping.\n", volumeId, c.ID) continue } if err := srv.runtime.volumes.Delete(volumeId); err != nil { @@ -715,7 +715,7 @@ func (srv *Server) ImageDelete(name string) error { if err != nil { return fmt.Errorf("No such image: %s", name) } - if err := srv.runtime.graph.Delete(img.Id); err != nil { + if err := srv.runtime.graph.Delete(img.ID); err != nil { return fmt.Errorf("Error deleting image %s: %s", name, err.Error()) } return nil @@ -735,7 +735,7 @@ func (srv *Server) ImageGetCached(imgId string, config *Config) (*Image, error) if _, exists := imageMap[img.Parent]; !exists { imageMap[img.Parent] = make(map[string]struct{}) } - imageMap[img.Parent][img.Id] = struct{}{} + imageMap[img.Parent][img.ID] = struct{}{} } // Loop on the children of the given image and check the config diff --git a/server_test.go b/server_test.go index b96e1dd5eb..ab43dd77e8 100644 --- a/server_test.go +++ b/server_test.go @@ -13,7 +13,7 @@ func TestCreateRm(t *testing.T) { srv := &Server{runtime: runtime} - config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "echo test"}, nil) + config, _, err := ParseRun([]string{GetTestImage(runtime).ID, "echo test"}, nil) if err != nil { t.Fatal(err) } @@ -46,7 +46,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) { srv := &Server{runtime: runtime} - config, _, err := ParseRun([]string{GetTestImage(runtime).Id, "/bin/cat"}, nil) + config, _, err := ParseRun([]string{GetTestImage(runtime).ID, "/bin/cat"}, nil) if err != nil { t.Fatal(err) } diff --git a/tags.go b/tags.go index 5bc2978e09..d862289ce6 100644 --- a/tags.go +++ b/tags.go @@ -11,7 +11,7 @@ import ( "strings" ) -const DEFAULT_TAG = "latest" +const DEFAULTTAG = "latest" type TagStore struct { path string @@ -72,7 +72,7 @@ func (store *TagStore) LookupImage(name string) (*Image, error) { // (so we can pass all errors here) repoAndTag := strings.SplitN(name, ":", 2) if len(repoAndTag) == 1 { - repoAndTag = append(repoAndTag, DEFAULT_TAG) + repoAndTag = append(repoAndTag, DEFAULTTAG) } if i, err := store.GetImage(repoAndTag[0], repoAndTag[1]); err != nil { return nil, err @@ -87,27 +87,27 @@ func (store *TagStore) LookupImage(name string) (*Image, error) { // Return a reverse-lookup table of all the names which refer to each image // Eg. {"43b5f19b10584": {"base:latest", "base:v1"}} -func (store *TagStore) ById() map[string][]string { - byId := make(map[string][]string) +func (store *TagStore) ByID() map[string][]string { + byID := make(map[string][]string) for repoName, repository := range store.Repositories { for tag, id := range repository { name := repoName + ":" + tag - if _, exists := byId[id]; !exists { - byId[id] = []string{name} + if _, exists := byID[id]; !exists { + byID[id] = []string{name} } else { - byId[id] = append(byId[id], name) - sort.Strings(byId[id]) + byID[id] = append(byID[id], name) + sort.Strings(byID[id]) } } } - return byId + return byID } func (store *TagStore) ImageName(id string) string { - if names, exists := store.ById()[id]; exists && len(names) > 0 { + if names, exists := store.ByID()[id]; exists && len(names) > 0 { return names[0] } - return utils.TruncateId(id) + return utils.TruncateID(id) } func (store *TagStore) Set(repoName, tag, imageName string, force bool) error { @@ -116,7 +116,7 @@ func (store *TagStore) Set(repoName, tag, imageName string, force bool) error { return err } if tag == "" { - tag = DEFAULT_TAG + tag = DEFAULTTAG } if err := validateRepoName(repoName); err != nil { return err @@ -137,7 +137,7 @@ func (store *TagStore) Set(repoName, tag, imageName string, force bool) error { } store.Repositories[repoName] = repo } - repo[tag] = img.Id + repo[tag] = img.ID return store.Save() } diff --git a/utils/utils.go b/utils/utils.go index eb6b35677e..c84eff2d2c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -349,11 +349,11 @@ func (idx *TruncIndex) Get(s string) (string, error) { return string(idx.bytes[before:after]), err } -// TruncateId returns a shorthand version of a string identifier for convenience. +// TruncateID returns a shorthand version of a string identifier for convenience. // A collision with other shorthands is very unlikely, but possible. // In case of a collision a lookup with TruncIndex.Get() will fail, and the caller // will need to use a langer prefix, or the full-length Id. -func TruncateId(id string) string { +func TruncateID(id string) string { shortLen := 12 if len(id) < shortLen { shortLen = len(id) @@ -566,7 +566,7 @@ func NewWriteFlusher(w io.Writer) *WriteFlusher { return &WriteFlusher{w: w, flusher: flusher} } -type JsonMessage struct { +type JSONMessage struct { Status string `json:"status,omitempty"` Progress string `json:"progress,omitempty"` Error string `json:"error,omitempty"` @@ -585,7 +585,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte sf.used = true str := fmt.Sprintf(format, a...) if sf.json { - b, err := json.Marshal(&JsonMessage{Status:str}); + b, err := json.Marshal(&JSONMessage{Status:str}); if err != nil { return sf.FormatError(err) } @@ -597,7 +597,7 @@ func (sf *StreamFormatter) FormatStatus(format string, a ...interface{}) []byte func (sf *StreamFormatter) FormatError(err error) []byte { sf.used = true if sf.json { - if b, err := json.Marshal(&JsonMessage{Error:err.Error()}); err == nil { + if b, err := json.Marshal(&JSONMessage{Error:err.Error()}); err == nil { return b } return []byte("{\"error\":\"format error\"}") @@ -608,7 +608,7 @@ func (sf *StreamFormatter) FormatError(err error) []byte { func (sf *StreamFormatter) FormatProgress(action, str string) []byte { sf.used = true if sf.json { - b, err := json.Marshal(&JsonMessage{Progress:str}) + b, err := json.Marshal(&JSONMessage{Progress:str}) if err != nil { return nil } From c000ef194c0259bfe631222b19a2bc204281f836 Mon Sep 17 00:00:00 2001 From: John Costa Date: Tue, 4 Jun 2013 16:01:38 -0400 Subject: [PATCH 77/79] Remove provider specifc language --- docs/sources/installation/ubuntulinux.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/sources/installation/ubuntulinux.rst b/docs/sources/installation/ubuntulinux.rst index 5ccbd59c29..ed592d3a9d 100644 --- a/docs/sources/installation/ubuntulinux.rst +++ b/docs/sources/installation/ubuntulinux.rst @@ -94,9 +94,8 @@ have AUFS filesystem support enabled, so we need to install it. **add-apt-repository support** -Some installations of Ubuntu 13.04 (Digital Ocean's Ubuntu 13.04 x64 Server in -this case) require software-properties-common to be installed before being able -to use add-apt-repository. +Some installations of Ubuntu 13.04 require ``software-properties-common`` to be +installed before being able to use add-apt-repository. .. code-block:: bash From 7ef9833dbb299ebf796092a6921127ea77d38337 Mon Sep 17 00:00:00 2001 From: "Guillaume J. Charmes" Date: Tue, 4 Jun 2013 14:26:40 -0700 Subject: [PATCH 78/79] Put back panic for go1.0.3 compatibility --- container.go | 3 +++ network.go | 1 + 2 files changed, 4 insertions(+) diff --git a/container.go b/container.go index 2e383c0d4b..29c07eea0b 100644 --- a/container.go +++ b/container.go @@ -606,6 +606,7 @@ func (container *Container) waitLxc() error { } time.Sleep(500 * time.Millisecond) } + panic("Unreachable") } func (container *Container) monitor() { @@ -794,6 +795,8 @@ func (container *Container) WaitTimeout(timeout time.Duration) error { case <-done: return nil } + + panic("Unreachable") } func (container *Container) EnsureMounted() error { diff --git a/network.go b/network.go index f78e320fd2..690d252ec2 100644 --- a/network.go +++ b/network.go @@ -257,6 +257,7 @@ func proxy(listener net.Listener, proto, address string) error { utils.Debugf("Connected to backend, splicing") splice(src, dst) } + panic("Unreachable") } func halfSplice(dst, src net.Conn) error { From 7e6ede63794b54bcc0d67d86ea60e76b701d286f Mon Sep 17 00:00:00 2001 From: Louis Opter Date: Tue, 4 Jun 2013 15:24:25 -0700 Subject: [PATCH 79/79] Print the container id before the hijack in `docker run` (see also #804) This is useful when you want to get the container id before you start to interact with stdin (which is what I'm doing in dotcloud/sandbox). --- commands.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/commands.go b/commands.go index f12e9bcb11..71a6f87e04 100644 --- a/commands.go +++ b/commands.go @@ -1228,6 +1228,9 @@ func (cli *DockerCli) CmdRun(args ...string) error { return err } + if !config.AttachStdout && !config.AttachStderr { + fmt.Println(out.ID) + } if connections > 0 { chErrors := make(chan error, connections) cli.monitorTtySize(out.ID) @@ -1262,9 +1265,6 @@ func (cli *DockerCli) CmdRun(args ...string) error { connections -= 1 } } - if !config.AttachStdout && !config.AttachStderr { - fmt.Println(out.ID) - } return nil }