func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, local, remote, askedTag, registryEp string, sf *utils.StreamFormatter) error { out.Write(sf.FormatStatus("Pulling repository %s from %s", local, auth.IndexServerAddress())) var repoData *registry.RepositoryData var err error if registryEp == "" { repoData, err = r.GetRepositoryData(remote) if err != nil { return err } utils.Debugf("Updating checksums") // Reload the json file to make sure not to overwrite faster sums if err := srv.runtime.graph.UpdateChecksums(repoData.ImgList); err != nil { return err } } else { repoData = ®istry.RepositoryData{ Tokens: []string{}, ImgList: make(map[string]*registry.ImgData), Endpoints: []string{registryEp}, } } utils.Debugf("Retrieving the tag list") tagsList, err := r.GetRemoteTags(repoData.Endpoints, remote, repoData.Tokens) if err != nil { utils.Debugf("%v", err) return err } if registryEp != "" { for tag, id := range tagsList { repoData.ImgList[id] = ®istry.ImgData{ ID: id, Tag: tag, Checksum: "", } } } utils.Debugf("Registering tags") // If no tag has been specified, pull them all if askedTag == "" { for tag, id := range tagsList { repoData.ImgList[id].Tag = tag } } else { // Otherwise, check that the tag exists and use only that one id, exists := tagsList[askedTag] if !exists { return fmt.Errorf("Tag %s not found in repositoy %s", askedTag, local) } repoData.ImgList[id].Tag = askedTag } 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) continue } out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.ID, img.Tag, remote)) success := false for _, ep := range repoData.Endpoints { if !(strings.HasPrefix(ep, "http://") || strings.HasPrefix(ep, "https://")) { ep = fmt.Sprintf("%s://%s", registry.UrlScheme(), ep) } if err := srv.pullImage(r, out, img.ID, 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 } success = true break } if !success { return fmt.Errorf("Could not find repository on any of the indexed registries.") } } for tag, id := range tagsList { if askedTag != "" && tag != askedTag { continue } if err := srv.runtime.repositories.Set(local, tag, id, true); err != nil { return err } } if err := srv.runtime.repositories.Save(); err != nil { return err } return nil }
func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag, indexEp string, sf *utils.StreamFormatter, parallel bool) error { out.Write(sf.FormatStatus("", "Pulling repository %s", localName)) repoData, err := r.GetRepositoryData(indexEp, remoteName) if err != nil { return err } utils.Debugf("Retrieving the tag list") tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens) if err != nil { utils.Debugf("%v", err) return err } for tag, id := range tagsList { repoData.ImgList[id] = ®istry.ImgData{ ID: id, Tag: tag, Checksum: "", } } utils.Debugf("Registering tags") // If no tag has been specified, pull them all if askedTag == "" { for tag, id := range tagsList { repoData.ImgList[id].Tag = tag } } else { // Otherwise, check that the tag exists and use only that one id, exists := tagsList[askedTag] if !exists { return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName) } repoData.ImgList[id].Tag = askedTag } errors := make(chan error) for _, image := range repoData.ImgList { downloadImage := func(img *registry.ImgData) { if askedTag != "" && img.Tag != askedTag { utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID) if parallel { errors <- nil } return } if img.Tag == "" { utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID) if parallel { errors <- nil } return } // ensure no two downloads of the same image happen at the same time if err := srv.poolAdd("pull", "img:"+img.ID); err != nil { utils.Debugf("Image (id: %s) pull is already running, skipping: %v", img.ID, err) if parallel { errors <- nil } return } defer srv.poolRemove("pull", "img:"+img.ID) out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Pulling", fmt.Sprintf("image (%s) from %s", img.Tag, localName))) success := false var lastErr error for _, ep := range repoData.Endpoints { out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Pulling", fmt.Sprintf("image (%s) from %s, endpoint: %s", img.Tag, localName, ep))) if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil { // Its not ideal that only the last error is returned, it would be better to concatenate the errors. // As the error is also given to the output stream the user will see the error. lastErr = err out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Error pulling", fmt.Sprintf("image (%s) from %s, endpoint: %s, %s", img.Tag, localName, ep, err))) continue } success = true break } if !success { out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Error pulling", fmt.Sprintf("image (%s) from %s, %s", img.Tag, localName, lastErr))) if parallel { errors <- fmt.Errorf("Could not find repository on any of the indexed registries.") return } } out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Download", "complete")) if parallel { errors <- nil } } if parallel { go downloadImage(image) } else { downloadImage(image) } } if parallel { var lastError error for i := 0; i < len(repoData.ImgList); i++ { if err := <-errors; err != nil { lastError = err } } if lastError != nil { return lastError } } for tag, id := range tagsList { if askedTag != "" && tag != askedTag { continue } if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil { return err } } if err := srv.runtime.repositories.Save(); err != nil { return err } return nil }
func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag, indexEp string, sf *utils.StreamFormatter) error { out.Write(sf.FormatStatus("Pulling repository %s", localName)) repoData, err := r.GetRepositoryData(indexEp, remoteName) if err != nil { return err } utils.Debugf("Updating checksums") // Reload the json file to make sure not to overwrite faster sums if err := srv.runtime.graph.UpdateChecksums(repoData.ImgList); err != nil { return err } utils.Debugf("Retrieving the tag list") tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens) if err != nil { utils.Debugf("%v", err) return err } for tag, id := range tagsList { repoData.ImgList[id] = ®istry.ImgData{ ID: id, Tag: tag, Checksum: "", } } utils.Debugf("Registering tags") // If no tag has been specified, pull them all if askedTag == "" { for tag, id := range tagsList { repoData.ImgList[id].Tag = tag } } else { // Otherwise, check that the tag exists and use only that one id, exists := tagsList[askedTag] if !exists { return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName) } repoData.ImgList[id].Tag = askedTag } 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) continue } if img.Tag == "" { utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID) continue } out.Write(sf.FormatStatus("Pulling image %s (%s) from %s", img.ID, img.Tag, localName)) success := false for _, ep := range repoData.Endpoints { if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil { out.Write(sf.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint", askedTag, err)) continue } success = true break } if !success { return fmt.Errorf("Could not find repository on any of the indexed registries.") } } for tag, id := range tagsList { if askedTag != "" && tag != askedTag { continue } if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil { return err } } if err := srv.runtime.repositories.Save(); err != nil { return err } return nil }
func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, localName, remoteName, askedTag, indexEp string, sf *utils.StreamFormatter, parallel bool) error { out.Write(sf.FormatStatus("", "Pulling repository %s", localName)) repoData, err := r.GetRepositoryData(indexEp, remoteName) if err != nil { return err } utils.Debugf("Retrieving the tag list") tagsList, err := r.GetRemoteTags(repoData.Endpoints, remoteName, repoData.Tokens) if err != nil { utils.Debugf("%v", err) return err } for tag, id := range tagsList { repoData.ImgList[id] = ®istry.ImgData{ ID: id, Tag: tag, Checksum: "", } } utils.Debugf("Registering tags") // If no tag has been specified, pull them all if askedTag == "" { for tag, id := range tagsList { repoData.ImgList[id].Tag = tag } } else { // Otherwise, check that the tag exists and use only that one id, exists := tagsList[askedTag] if !exists { return fmt.Errorf("Tag %s not found in repository %s", askedTag, localName) } repoData.ImgList[id].Tag = askedTag } errors := make(chan error) for _, image := range repoData.ImgList { downloadImage := func(img *registry.ImgData) { if askedTag != "" && img.Tag != askedTag { utils.Debugf("(%s) does not match %s (id: %s), skipping", img.Tag, askedTag, img.ID) errors <- nil return } if img.Tag == "" { utils.Debugf("Image (id: %s) present in this repository but untagged, skipping", img.ID) errors <- nil return } out.Write(sf.FormatProgress(utils.TruncateID(img.ID), "Pulling", fmt.Sprintf("image (%s) from %s", img.Tag, localName))) success := false for _, ep := range repoData.Endpoints { if err := srv.pullImage(r, out, img.ID, ep, repoData.Tokens, sf); err != nil { out.Write(sf.FormatStatus(utils.TruncateID(img.ID), "Error while retrieving image for tag: %s (%s); checking next endpoint", askedTag, err)) continue } success = true break } if !success { errors <- fmt.Errorf("Could not find repository on any of the indexed registries.") } errors <- nil } if parallel { go downloadImage(image) } else { downloadImage(image) } } if parallel { for i := 0; i < len(repoData.ImgList); i++ { if err := <-errors; err != nil { return err } } } for tag, id := range tagsList { if askedTag != "" && tag != askedTag { continue } if err := srv.runtime.repositories.Set(localName, tag, id, true); err != nil { return err } } if err := srv.runtime.repositories.Save(); err != nil { return err } return nil }
func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, askedTag string, json bool) error { fmt.Fprintf(out, utils.FormatStatus("Pulling repository %s from %s", json), remote, auth.IndexServerAddress()) repoData, err := r.GetRepositoryData(remote) if err != nil { return err } utils.Debugf("Updating checksums") // Reload the json file to make sure not to overwrite faster sums if err := srv.runtime.graph.UpdateChecksums(repoData.ImgList); err != nil { return err } utils.Debugf("Retrieving the tag list") tagsList, err := r.GetRemoteTags(repoData.Endpoints, remote, repoData.Tokens) if err != nil { return err } utils.Debugf("Registering tags") // If not specific tag have been asked, take all if askedTag == "" { for tag, id := range tagsList { repoData.ImgList[id].Tag = tag } } else { // Otherwise, check that the tag exists and use only that one if id, exists := tagsList[askedTag]; !exists { return fmt.Errorf("Tag %s not found in repositoy %s", askedTag, remote) } else { repoData.ImgList[id].Tag = askedTag } } 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) continue } fmt.Fprintf(out, utils.FormatStatus("Pulling image %s (%s) from %s", json), 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, json); err != nil { fmt.Fprintf(out, utils.FormatStatus("Error while retrieving image for tag: %s (%s); checking next endpoint\n", json), askedTag, err) continue } success = true break } if !success { return fmt.Errorf("Could not find repository on any of the indexed registries.") } } for tag, id := range tagsList { if askedTag != "" && tag != askedTag { continue } if err := srv.runtime.repositories.Set(remote, tag, id, true); err != nil { return err } } if err := srv.runtime.repositories.Save(); err != nil { return err } return nil }