diff --git a/server.go b/server.go index 6576fac0db..b07e85b44c 100644 --- a/server.go +++ b/server.go @@ -68,6 +68,7 @@ func (srv *Server) ImagesSearch(term string) ([]ApiSearch, error) { } func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error { + out = &utils.WriteFlusher{W: out} img, err := srv.runtime.repositories.LookupImage(name) if err != nil { return err @@ -98,7 +99,7 @@ func (srv *Server) ImageInsert(name, url, path string, out io.Writer) error { if err != nil { return err } - utils.FprintfFlush(out, "%s\n", img.Id) + fmt.Fprintf(out, "%s\n", img.Id) return nil } @@ -289,6 +290,7 @@ func (srv *Server) ContainerTag(name, repo, tag string, force bool) error { } func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []string) error { + out = &utils.WriteFlusher{W: out} history, err := srv.registry.GetRemoteHistory(imgId, registry, token) if err != nil { return err @@ -298,7 +300,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) { - utils.FprintfFlush(out, "Pulling %s metadata\r\n", id) + fmt.Fprintf(out, "Pulling %s metadata\r\n", id) imgJson, err := srv.registry.GetRemoteImageJson(id, registry, token) if err != nil { // FIXME: Keep goging in case of error? @@ -310,7 +312,7 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri } // Get the layer - utils.FprintfFlush(out, "Pulling %s fs layer\r\n", img.Id) + fmt.Fprintf(out, "Pulling %s fs layer\r\n", img.Id) layer, contentLength, err := srv.registry.GetRemoteImageLayer(img.Id, registry, token) if err != nil { return err @@ -324,7 +326,8 @@ func (srv *Server) pullImage(out io.Writer, imgId, registry string, token []stri } func (srv *Server) pullRepository(out io.Writer, remote, askedTag string) error { - utils.FprintfFlush(out, "Pulling repository %s from %s\r\n", remote, auth.IndexServerAddress()) + out = &utils.WriteFlusher{W: out} + fmt.Fprintf(out, "Pulling repository %s from %s\r\n", remote, auth.IndexServerAddress()) repoData, err := srv.registry.GetRepositoryData(remote) if err != nil { return err @@ -350,11 +353,11 @@ func (srv *Server) pullRepository(out io.Writer, remote, askedTag string) error if askedTag != "" && askedTag != img.Tag { continue } - utils.FprintfFlush(out, "Pulling image %s (%s) from %s\n", img.Id, img.Tag, remote) + fmt.Fprintf(out, "Pulling image %s (%s) from %s\n", img.Id, img.Tag, remote) success := false for _, ep := range repoData.Endpoints { if err := srv.pullImage(out, img.Id, "https://"+ep+"/v1", repoData.Tokens); err != nil { - utils.FprintfFlush(out, "Error while retrieving image for tag: %s (%s); checking next endpoint\n", askedTag, err) + fmt.Fprintf(out, "Error while retrieving image for tag: %s (%s); checking next endpoint\n", askedTag, err) continue } if err := srv.runtime.repositories.Set(remote, img.Tag, img.Id, true); err != nil { @@ -462,12 +465,13 @@ func (srv *Server) getImageList(localRepo map[string]string) ([]*registry.ImgDat } func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[string]string) error { - utils.FprintfFlush(out, "Processing checksums\n") + out = &utils.WriteFlusher{W: out} + fmt.Fprintf(out, "Processing checksums\n") imgList, err := srv.getImageList(localRepo) if err != nil { return err } - utils.FprintfFlush(out, "Sending image list\n") + fmt.Fprintf(out, "Sending image list\n") repoData, err := srv.registry.PushImageJsonIndex(name, imgList, false) if err != nil { @@ -476,18 +480,18 @@ func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[stri // FIXME: Send only needed images for _, ep := range repoData.Endpoints { - utils.FprintfFlush(out, "Pushing repository %s to %s (%d tags)\r\n", name, ep, len(localRepo)) + fmt.Fprintf(out, "Pushing repository %s to %s (%d tags)\r\n", name, ep, len(localRepo)) // For each image within the repo, push them for _, elem := range imgList { if _, exists := repoData.ImgList[elem.Id]; exists { - utils.FprintfFlush(out, "Image %s already on registry, skipping\n", name) + fmt.Fprintf(out, "Image %s already on registry, skipping\n", name) continue } if err := srv.pushImage(out, name, elem.Id, ep, repoData.Tokens); err != nil { // FIXME: Continue on error? return err } - utils.FprintfFlush(out, "Pushing tags for rev [%s] on {%s}\n", elem.Id, ep+"/users/"+name+"/"+elem.Tag) + fmt.Fprintf(out, "Pushing tags for rev [%s] on {%s}\n", elem.Id, ep+"/users/"+name+"/"+elem.Tag) if err := srv.registry.PushRegistryTag(name, elem.Id, elem.Tag, ep, repoData.Tokens); err != nil { return err } @@ -501,11 +505,12 @@ func (srv *Server) pushRepository(out io.Writer, name string, localRepo map[stri } func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []string) error { + out = &utils.WriteFlusher{W: 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) } - utils.FprintfFlush(out, "Pushing %s\r\n", imgId) + fmt.Fprintf(out, "Pushing %s\r\n", imgId) // Make sure we have the image's checksum checksum, err := srv.getChecksum(imgId) @@ -520,7 +525,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 { - utils.FprintfFlush(out, "Image %s already uploaded ; skipping\n", imgData.Id) + fmt.Fprintf(out, "Image %s already uploaded ; skipping\n", imgData.Id) return nil } return err @@ -560,9 +565,10 @@ func (srv *Server) pushImage(out io.Writer, remote, imgId, ep string, token []st } func (srv *Server) ImagePush(name, registry string, out io.Writer) error { + out = &utils.WriteFlusher{W: out} img, err := srv.runtime.graph.Get(name) if err != nil { - utils.FprintfFlush(out, "The push refers to a repository [%s] (len: %d)\n", name, len(srv.runtime.repositories.Repositories[name])) + fmt.Fprintf(out, "The push refers to a repository [%s] (len: %d)\n", 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 { @@ -573,7 +579,7 @@ func (srv *Server) ImagePush(name, registry string, out io.Writer) error { return err } - utils.FprintfFlush(out, "The push refers to an image: [%s]\n", name) + fmt.Fprintf(out, "The push refers to an image: [%s]\n", name) if err := srv.pushImage(out, name, img.Id, registry, nil); err != nil { return err } @@ -589,14 +595,14 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write } else { u, err := url.Parse(src) if err != nil { - utils.FprintfFlush(out, "Error: %s\n", err) + fmt.Fprintf(out, "Error: %s\n", err) } if u.Scheme == "" { u.Scheme = "http" u.Host = src u.Path = "" } - utils.FprintfFlush(out, "Downloading from %s\n", u) + fmt.Fprintf(out, "Downloading from %s\n", u) // Download with curl (pretty progress bar) // If curl is not available, fallback to http.Get() resp, err = utils.Download(u.String(), out) @@ -615,7 +621,7 @@ func (srv *Server) ImageImport(src, repo, tag string, in io.Reader, out io.Write return err } } - utils.FprintfFlush(out, "%s\n", img.ShortId()) + fmt.Fprintf(out, "%s\n", img.ShortId()) return nil } diff --git a/utils/utils.go b/utils/utils.go index 6a6a9f95b5..a2fd3bde6d 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -84,15 +84,15 @@ func (r *progressReader) Read(p []byte) (n int, err error) { } if r.readProgress-r.lastUpdate > updateEvery || err != nil { if r.readTotal > 0 { - FprintfFlush(r.output, r.template+"\r", r.readProgress, r.readTotal, fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) + fmt.Fprintf(r.output, r.template+"\r", r.readProgress, r.readTotal, fmt.Sprintf("%.0f%%", float64(r.readProgress)/float64(r.readTotal)*100)) } else { - FprintfFlush(r.output, r.template+"\r", r.readProgress, "?", "n/a") + fmt.Fprintf(r.output, r.template+"\r", r.readProgress, "?", "n/a") } r.lastUpdate = r.readProgress } // Send newline when complete if err != nil { - FprintfFlush(r.output, "\n") + fmt.Fprintf(r.output, "\n") } return read, err @@ -104,7 +104,7 @@ func ProgressReader(r io.ReadCloser, size int, output io.Writer, template string if template == "" { template = "%v/%v (%v)" } - return &progressReader{r, output, size, 0, 0, template} + return &progressReader{r, &WriteFlusher{W: output}, size, 0, 0, template} } // HumanDuration returns a human-readable approximation of a duration @@ -531,11 +531,14 @@ func GetKernelVersion() (*KernelVersionInfo, error) { }, nil } +type WriteFlusher struct { + W io.Writer +} -func FprintfFlush(w io.Writer, format string, a ...interface{}) (n int, err error) { - n, err = fmt.Fprintf(w, format, a...) - if f, ok := w.(http.Flusher); ok { +func (wf *WriteFlusher) Write(b []byte) (n int, err error) { + n, err = wf.W.Write(b) + if f, ok := wf.W.(http.Flusher); ok { f.Flush() } return n, err -} \ No newline at end of file +}