func (srv *Server) pushRepository(r *registry.Registry, out io.Writer, name, registryEp string, localRepo map[string]string, sf *utils.StreamFormatter) error { out = utils.NewWriteFlusher(out) out.Write(sf.FormatStatus("Processing checksums")) imgList, err := srv.getImageList(localRepo) if err != nil { return err } out.Write(sf.FormatStatus("Sending image list")) srvName := name parts := strings.Split(name, "/") if len(parts) > 2 { srvName = fmt.Sprintf("src/%s", url.QueryEscape(strings.Join(parts, "/"))) } var repoData *registry.RepositoryData if registryEp == "" { repoData, err = r.PushImageJSONIndex(name, imgList, false, nil) if err != nil { return err } } else { repoData = ®istry.RepositoryData{ ImgList: make(map[string]*registry.ImgData), Tokens: []string{}, Endpoints: []string{registryEp}, } tagsList, err := r.GetRemoteTags(repoData.Endpoints, name, repoData.Tokens) if err != nil && err.Error() != "Repository not found" { return err } else if err == nil { for tag, id := range tagsList { repoData.ImgList[id] = ®istry.ImgData{ ID: id, Tag: tag, Checksum: "", } } } } for _, ep := range repoData.Endpoints { if !(strings.HasPrefix(ep, "http://") || strings.HasPrefix(ep, "https://")) { ep = fmt.Sprintf("%s://%s", registry.UrlScheme(), ep) } 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 { out.Write(sf.FormatStatus("Image %s already on registry, skipping", name)) continue } else if registryEp != "" && r.LookupRemoteImage(elem.ID, registryEp, repoData.Tokens) { fmt.Fprintf(out, "Image %s already on registry, skipping\n", name) continue } 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+"/repositories/"+srvName+"/tags/"+elem.Tag)) if err := r.PushRegistryTag(srvName, elem.ID, elem.Tag, ep, repoData.Tokens); err != nil { return err } } } if registryEp == "" { if _, err := r.PushImageJSONIndex(name, imgList, true, repoData.Endpoints); err != nil { return err } } return nil }
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 }