// GetManifests handles GET /api/repositories/manifests func (ra *RepositoryAPI) GetManifests() { repoName := ra.GetString("repo_name") tag := ra.GetString("tag") if len(repoName) == 0 || len(tag) == 0 { ra.CustomAbort(http.StatusBadRequest, "repo_name or tag is nil") } version := ra.GetString("version") if len(version) == 0 { version = "v2" } if version != "v1" && version != "v2" { ra.CustomAbort(http.StatusBadRequest, "version should be v1 or v2") } projectName, _ := utils.ParseRepository(repoName) project, err := dao.GetProjectByName(projectName) if err != nil { log.Errorf("failed to get project %s: %v", projectName, err) ra.CustomAbort(http.StatusInternalServerError, "") } if project == nil { ra.CustomAbort(http.StatusNotFound, fmt.Sprintf("project %s not found", projectName)) } if project.Public == 0 { userID := ra.ValidateUser() if !checkProjectPermission(userID, project.ProjectID) { ra.CustomAbort(http.StatusForbidden, "") } } rc, err := ra.initRepositoryClient(repoName) if err != nil { log.Errorf("error occurred while initializing repository client for %s: %v", repoName, err) ra.CustomAbort(http.StatusInternalServerError, "internal error") } result := struct { Manifest interface{} `json:"manifest"` Config interface{} `json:"config,omitempty" ` }{} mediaTypes := []string{} switch version { case "v1": mediaTypes = append(mediaTypes, schema1.MediaTypeManifest) case "v2": mediaTypes = append(mediaTypes, schema2.MediaTypeManifest) } _, mediaType, payload, err := rc.PullManifest(tag, mediaTypes) if err != nil { if regErr, ok := err.(*registry_error.Error); ok { ra.CustomAbort(regErr.StatusCode, regErr.Detail) } log.Errorf("error occurred while getting manifest of %s:%s: %v", repoName, tag, err) ra.CustomAbort(http.StatusInternalServerError, "internal error") } manifest, _, err := registry.UnMarshal(mediaType, payload) if err != nil { log.Errorf("an error occurred while parsing manifest of %s:%s: %v", repoName, tag, err) ra.CustomAbort(http.StatusInternalServerError, "") } result.Manifest = manifest deserializedmanifest, ok := manifest.(*schema2.DeserializedManifest) if ok { _, data, err := rc.PullBlob(deserializedmanifest.Target().Digest.String()) if err != nil { log.Errorf("failed to get config of manifest %s:%s: %v", repoName, tag, err) ra.CustomAbort(http.StatusInternalServerError, "") } b, err := ioutil.ReadAll(data) if err != nil { log.Errorf("failed to read config of manifest %s:%s: %v", repoName, tag, err) ra.CustomAbort(http.StatusInternalServerError, "") } result.Config = string(b) } ra.Data["json"] = result ra.ServeJSON() }
func (m *ManifestPuller) enter() (string, error) { if len(m.tags) == 0 { m.logger.Infof("no tag needs to be replicated, next state is \"finished\"") return models.JobFinished, nil } name := m.repository tag := m.tags[0] acceptMediaTypes := []string{schema1.MediaTypeManifest, schema2.MediaTypeManifest} digest, mediaType, payload, err := m.srcClient.PullManifest(tag, acceptMediaTypes) if err != nil { m.logger.Errorf("an error occurred while pulling manifest of %s:%s from %s: %v", name, tag, m.srcURL, err) return "", err } m.digest = digest m.logger.Infof("manifest of %s:%s pulled successfully from %s: %s", name, tag, m.srcURL, digest) if strings.Contains(mediaType, "application/json") { mediaType = schema1.MediaTypeManifest } manifest, _, err := registry.UnMarshal(mediaType, payload) if err != nil { m.logger.Errorf("an error occurred while parsing manifest of %s:%s from %s: %v", name, tag, m.srcURL, err) return "", err } m.manifest = manifest // all blobs(layers and config) var blobs []string for _, discriptor := range manifest.References() { blobs = append(blobs, discriptor.Digest.String()) } // config is also need to be transferred if the schema of manifest is v2 manifest2, ok := manifest.(*schema2.DeserializedManifest) if ok { blobs = append(blobs, manifest2.Target().Digest.String()) } m.logger.Infof("all blobs of %s:%s from %s: %v", name, tag, m.srcURL, blobs) for _, blob := range blobs { exist, ok := m.blobsExistence[blob] if !ok { exist, err = m.dstClient.BlobExist(blob) if err != nil { m.logger.Errorf("an error occurred while checking existence of blob %s of %s:%s on %s: %v", blob, name, tag, m.dstURL, err) return "", err } m.blobsExistence[blob] = exist } if !exist { m.blobs = append(m.blobs, blob) } else { m.logger.Infof("blob %s of %s:%s already exists in %s", blob, name, tag, m.dstURL) } } m.logger.Infof("blobs of %s:%s need to be transferred to %s: %v", name, tag, m.dstURL, m.blobs) return StateTransferBlob, nil }