func GetManifestsV2Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { t := new(models.Tag) namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") if err := t.Get(namespace, repository, ctx.Params(":tag")); err != nil { log.Error("[REGISTRY API V2] Manifest not found: %v", err.Error()) result, _ := json.Marshal(map[string]string{"message": "Manifest not found"}) return http.StatusNotFound, result } digest, err := utils.DigestManifest([]byte(t.Manifest)) if err != nil { log.Error("[REGISTRY API V2] Get manifest digest failed: %v", err.Error()) result, _ := json.Marshal(map[string]string{"message": "Get manifest digest failed"}) return http.StatusBadRequest, result } ctx.Resp.Header().Set("Content-Type", "application/json; charset=utf-8") ctx.Resp.Header().Set("Docker-Content-Digest", digest) ctx.Resp.Header().Set("Content-Length", fmt.Sprint(len(t.Manifest))) return http.StatusOK, []byte(t.Manifest) }
func GetTagsListV2Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") r := new(models.Repository) if has, _, err := r.Has(namespace, repository); err != nil || has == false { log.Error("[REGISTRY API V2] Repository not found: %v", repository) result, _ := json.Marshal(map[string]string{"message": "Repository not found"}) return http.StatusNotFound, result } data := map[string]interface{}{} tags := []string{} data["name"] = fmt.Sprintf("%s/%s", namespace, repository) for _, value := range r.Tags { t := new(models.Tag) if err := t.GetByKey(value); err != nil { log.Error("[REGISTRY API V2] Tag not found: %v", err.Error()) result, _ := json.Marshal(map[string]string{"message": "Tag not found"}) return http.StatusNotFound, result } tags = append(tags, t.Name) } data["tags"] = tags result, _ := json.Marshal(data) return http.StatusOK, result }
func GetTagV1Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") r := new(models.Repository) if exists, err := r.Get(namespace, repository); err != nil { log.Error("[REGISTRY API V1] Failed to get repository %v/%v context: %v", namespace, repository, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to get repository context"}) return http.StatusBadRequest, result } else if exists == false { log.Error("[REGISTRY API V1] Not found repository %v/%v", namespace, repository) result, _ := json.Marshal(map[string]string{"message": "Not found repository"}) return http.StatusNotFound, result } tags := map[string]string{} tagslist := r.GetTagslist() for _, tagname := range tagslist { t := new(models.Tag) if exists, err := t.Get(namespace, repository, tagname); err != nil || !exists { log.Error(fmt.Sprintf("[REGISTRY API V1] %s/%s %v is not exist", namespace, repository, tagname)) result, _ := json.Marshal(map[string]string{"message": "Tag is not exist"}) return http.StatusNotFound, result } tags[tagname] = t.ImageId } result, _ := json.Marshal(tags) return http.StatusOK, result }
func GetManifestsV2Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") tag := ctx.Params(":tag") t := new(models.Tag) if exists, err := t.Get(namespace, repository, tag); err != nil || !exists { log.Error("[REGISTRY API V2] Not found manifest: %v", err) result, _ := json.Marshal(map[string]string{"message": "Not found manifest"}) return http.StatusNotFound, result } digest, err := signature.DigestManifest([]byte(t.Manifest)) if err != nil { log.Error("[REGISTRY API V2] Failed to get manifest digest: %v", err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to get manifest digest"}) return http.StatusInternalServerError, result } contenttype := []string{"", "application/json; charset=utf-8", "application/vnd.docker.distribution.manifest.v2+json"} ctx.Resp.Header().Set("Content-Type", contenttype[t.Schema]) ctx.Resp.Header().Set("Docker-Content-Digest", digest) ctx.Resp.Header().Set("Content-Length", fmt.Sprint(len(t.Manifest))) return http.StatusOK, []byte(t.Manifest) }
func PostCompleteHandler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { imageId := ctx.Params(":imageId") repository := ctx.Params(":repository") body, _ := ctx.Req.Body().Bytes() if err := module.CheckClientStatus(body); err != nil { module.CleanCache(imageId, setting.APIVERSION_ACI) log.Error("[ACI API] Failed to push aci: %v", err.Error()) failmsg := module.FillRespMsg(false, err.Error(), "") result, _ := json.Marshal(failmsg) return http.StatusInternalServerError, result } namespace := ctx.Params(":namespace") acifile := ctx.Params(":acifile") signfile := ctx.Params(":signfile") //TODO: only for testing,pubkey will be read and saved via user management module pubkeyspath := module.GetPubkeysPath(namespace, repository, setting.APIVERSION_ACI) acifilepath := module.GetLayerPath(imageId, acifile, setting.APIVERSION_ACI) signfilepath := module.GetSignaturePath(imageId, signfile, setting.APIVERSION_ACI) manipath := module.GetManifestPath(imageId, setting.APIVERSION_ACI) if err := module.VerifyAciSignature(acifilepath, signfilepath, pubkeyspath); err != nil { module.CleanCache(imageId, setting.APIVERSION_ACI) log.Error("[ACI API] Failed to verify Aci: %v", err.Error()) failmsg := module.FillRespMsg(false, "", err.Error()) result, _ := json.Marshal(failmsg) return http.StatusInternalServerError, result } //If aci image is existent,it should update the db and delete the old image after executed successfully var oldimageId = "" tag := strings.Trim(acifile, ".aci") t := new(models.Tag) if exists, err := t.Get(namespace, repository, tag); err == nil && exists { oldimageId = t.ImageId } a := new(models.Aci) if err := a.Update(namespace, repository, tag, imageId, manipath, signfilepath, acifilepath); err != nil { module.CleanCache(imageId, setting.APIVERSION_ACI) log.Error("[ACI API] Failed to update %v/%v: %v", namespace, repository, err.Error()) failmsg := module.FillRespMsg(false, "", err.Error()) result, _ := json.Marshal(failmsg) return http.StatusInternalServerError, result } //Delete old aci directory after redis is updated if oldimageId != "" { module.CleanCache(oldimageId, setting.APIVERSION_ACI) } successmsg := module.FillRespMsg(true, "", "") result, _ := json.Marshal(successmsg) return http.StatusOK, result }
func GetACIHandler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") acifilename := ctx.Params(":acifilename") acifile := strings.Trim(acifilename, ".asc") tag := strings.Trim(acifile, ".aci") t := new(models.Tag) if exists, err := t.Get(namespace, repository, tag); err != nil || !exists { log.Error("[ACI API] Not found ACI %v/%v/%v", namespace, repository, acifilename) result, _ := json.Marshal(map[string]string{"message": "Not found ACI"}) return http.StatusNotFound, result } i := new(models.Image) if exists, err := i.Get(t.ImageId); err != nil || !exists { log.Error("[ACI API] Not found ACI %v/%v/%v", namespace, repository, acifilename) result, _ := json.Marshal(map[string]string{"message": "Not found ACI"}) return http.StatusNotFound, result } var filepath string if b := strings.Contains(acifilename, ".asc"); b == true { filepath = i.SignPath } else { filepath = i.AciPath } content, err := ioutil.ReadFile(filepath) if err != nil { log.Error("[ACI API] Failed to get ACI file %v: %v", filepath, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to get ACI file"}) return http.StatusInternalServerError, result } return http.StatusOK, content }
func (n *notification) Handler(ctx *macaron.Context) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") //Notification function just supports DockerV2 now r := new(models.Repository) if exists, err := r.Get(namespace, repository); err != nil || exists == false { return } if r.Version != setting.APIVERSION_V2 { return } actor := ActorRecord{Name: namespace} repo := fmt.Sprintf("%v/%v", namespace, repository) switch ctx.Req.Method { case "HEAD": digest := ctx.Params(":digest") tarsum := strings.Split(digest, ":")[1] i := new(models.Image) if exists, _ := i.Get(tarsum); exists == false { return } desc := Descriptor{ MediaType: DefaultMedisType, Size: i.Size, Digest: digest, } req := newReqRecord(utils.EncodeBasicAuth(namespace, "headblobsv2"), ctx.Req.Request) requrl, err := module.NewURLBuilderFromRequest(ctx.Req.Request).BuildBlobURL(repo, desc.Digest) if err != nil { fmt.Errorf("[REGISTRY API V2] Head blobs and get request URL failed, error:: %v", err.Error()) } b := newBridge(requrl, actor, req, notice) Err := b.createBlobEventAndWrite(EventActionPull, repo, desc) if Err.Err != nil { ctx.Resp.WriteHeader(http.StatusForbidden) return } else if Err.StatusCode >= 300 { ctx.Resp.WriteHeader(Err.StatusCode) return } case "GET": if flag := utils.Compare(ctx.Req.RequestURI, "/v2/"); flag == 0 { return } if flag := strings.Contains(ctx.Req.RequestURI, "/blobs/"); flag == true { digest := ctx.Params(":digest") tarsum := strings.Split(digest, ":")[1] i := new(models.Image) if exists, _ := i.Get(tarsum); exists == false { return } desc := Descriptor{ MediaType: BlobMediaType, Size: i.Size, Digest: digest, } req := newReqRecord(utils.EncodeBasicAuth(namespace, "getblobsv2"), ctx.Req.Request) requrl, err := module.NewURLBuilderFromRequest(ctx.Req.Request).BuildBlobURL(repo, desc.Digest) if err != nil { fmt.Errorf("[REGISTRY API V2] Get blobs and get request URL failed, error:: %v", err.Error()) } b := newBridge(requrl, actor, req, notice) Err := b.createBlobEventAndWrite(EventActionPull, repo, desc) if Err.Err != nil { ctx.Resp.WriteHeader(http.StatusForbidden) return } else if Err.StatusCode >= 300 { ctx.Resp.WriteHeader(Err.StatusCode) return } return } if flag := strings.Contains(ctx.Req.RequestURI, "/manifests/"); flag == true { t := new(models.Tag) if exists, err := t.Get(namespace, repository, ctx.Params(":tag")); err != nil || !exists { return } digest, err := utils.DigestManifest([]byte(t.Manifest)) if err != nil { fmt.Errorf("[REGISTRY API V2] Get manifest digest failed: %v", err.Error()) return } var sm SignedManifest if err := json.Unmarshal([]byte(t.Manifest), &sm); err != nil { fmt.Errorf("Unmarshal manifest error") } sm.Raw = make([]byte, len(t.Manifest), len(t.Manifest)) copy(sm.Raw, []byte(t.Manifest)) req := newReqRecord(utils.EncodeBasicAuth(namespace, "getmanifestv2"), ctx.Req.Request) requrl, err := module.NewURLBuilderFromRequest(ctx.Req.Request).BuildManifestURL(sm.Name, digest) if err != nil { fmt.Errorf("[REGISTRY API V2] Get manifest and get request URL failed, error:: %v", err.Error()) } b := newBridge(requrl, actor, req, notice) Err := b.createManifestEventAndWrite(EventActionPull, repo, &sm) if Err.Err != nil { ctx.Resp.WriteHeader(http.StatusForbidden) return } else if Err.StatusCode >= 300 { ctx.Resp.WriteHeader(Err.StatusCode) return } return } case "PUT": if flag := strings.Contains(ctx.Req.RequestURI, "/blobs/uploads/"); flag == true { param := ctx.Params(":uuid") uuid := strings.Split(param, "?")[0] layer, _ := ioutil.ReadFile(fmt.Sprintf("%v/%v/layer", setting.ImagePath, uuid)) digest := ctx.Query("digest") desc := Descriptor{ MediaType: DefaultMedisType, Size: int64(len(layer)), Digest: digest, } req := newReqRecord(utils.EncodeBasicAuth(namespace, "putblobsv2"), ctx.Req.Request) requrl, err := module.NewURLBuilderFromRequest(ctx.Req.Request).BuildBlobURL(repo, desc.Digest) if err != nil { fmt.Errorf("[REGISTRY API V2] Get blobs and get request URL failed, error:: %v", err.Error()) } b := newBridge(requrl, actor, req, notice) Err := b.createBlobEventAndWrite(EventActionPush, repo, desc) if Err.Err != nil { ctx.Resp.WriteHeader(http.StatusForbidden) return } else if Err.StatusCode >= 300 { ctx.Resp.WriteHeader(Err.StatusCode) return } return } if flag := strings.Contains(ctx.Req.RequestURI, "/manifests/"); flag == true { buf, _ := ctx.Req.Body().Bytes() handler.ManifestCtx = buf var sm SignedManifest if err := json.Unmarshal(buf, &sm); err != nil { fmt.Errorf("Unmarshal manifest error") } sm.Raw = make([]byte, len(buf), len(buf)) copy(sm.Raw, buf) digest, err := utils.DigestManifest(buf) if err != nil { fmt.Errorf("[REGISTRY API V2] Get manifest digest failed: %v", err.Error()) //return http.StatusBadRequest, result } req := newReqRecord(utils.EncodeBasicAuth(namespace, "putmanifestv2"), ctx.Req.Request) requrl, err := module.NewURLBuilderFromRequest(ctx.Req.Request).BuildManifestURL(sm.Name, digest) if err != nil { fmt.Errorf("[REGISTRY API V2] Put manifest and get request URL failed, error:: %v", err.Error()) } b := newBridge(requrl, actor, req, notice) Err := b.createManifestEventAndWrite(EventActionPush, repo, &sm) if Err.Err != nil { ctx.Resp.WriteHeader(http.StatusForbidden) return } else if Err.StatusCode >= 300 { ctx.Resp.WriteHeader(Err.StatusCode) return } return } default: return } }