func PutBlobsV2Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { desc := ctx.Params(":uuid") uuid := strings.Split(desc, "?")[0] digest := ctx.Query("digest") tarsum := strings.Split(digest, ":")[1] imagePathTmp := module.GetImagePath(uuid, setting.APIVERSION_V2) layerPathTmp := module.GetLayerPath(uuid, "layer", setting.APIVERSION_V2) imagePath := module.GetImagePath(tarsum, setting.APIVERSION_V2) layerPath := module.GetLayerPath(tarsum, "layer", setting.APIVERSION_V2) reqbody, _ := ctx.Req.Body().Bytes() layerlen, err := module.SaveLayerLocal(imagePathTmp, layerPathTmp, imagePath, layerPath, reqbody) if err != nil { log.Error("[REGISTRY API V2] Failed to save layer %v: %v", layerPath, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to save layer file"}) return http.StatusInternalServerError, result } //saving specific tarsum every times is in order to split the same tarsum in HEAD handler i := new(models.Image) i.Path, i.Size = layerPath, int64(layerlen) if err := i.Save(tarsum); err != nil { log.Error("[REGISTRY API V2] Failed to save tarsum %v: %v", tarsum, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to save tarsum"}) return http.StatusBadRequest, result } random := fmt.Sprintf("%s://%s/v2/%s/%s/blobs/%s", setting.ListenMode, setting.Domains, ctx.Params(":namespace"), ctx.Params(":repository"), digest) ctx.Resp.Header().Set("Content-Type", "text/plain; charset=utf-8") ctx.Resp.Header().Set("Docker-Content-Digest", digest) ctx.Resp.Header().Set("Location", random) result, _ := json.Marshal(map[string]string{}) return http.StatusCreated, result }
func PatchBlobsV2Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") desc := ctx.Params(":uuid") uuid := strings.Split(desc, "?")[0] imagePathTmp := module.GetImagePath(uuid, setting.APIVERSION_V2) layerPathTmp := module.GetLayerPath(uuid, "layer", setting.APIVERSION_V2) //saving specific tarsum every times is in order to split the same tarsum in HEAD handler if !utils.IsDirExist(imagePathTmp) { os.MkdirAll(imagePathTmp, os.ModePerm) } if _, err := os.Stat(layerPathTmp); err == nil { os.Remove(layerPathTmp) } data, _ := ctx.Req.Body().Bytes() if err := ioutil.WriteFile(layerPathTmp, data, 0777); err != nil { log.Error("[REGISTRY API V2] Failed to save layer %v: %v", layerPathTmp, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to save layer file"}) return http.StatusInternalServerError, result } state := utils.MD5(fmt.Sprintf("%s/%s/%d", namespace, repository, time.Now().UnixNano()/int64(time.Millisecond))) random := fmt.Sprintf("%s://%s/v2/%s/%s/blobs/uploads/%s?_state=%s", setting.ListenMode, setting.Domains, namespace, repository, uuid, state) ctx.Resp.Header().Set("Content-Type", "text/plain; charset=utf-8") ctx.Resp.Header().Set("Docker-Upload-Uuid", uuid) ctx.Resp.Header().Set("Location", random) ctx.Resp.Header().Set("Range", fmt.Sprintf("0-%v", len(data)-1)) result, _ := json.Marshal(map[string]string{}) return http.StatusAccepted, result }
//Support to push acis func PostUploadHandler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) { namespace := ctx.Params(":namespace") repository := ctx.Params(":repository") acifile := ctx.Params(":acifile") signfile := fmt.Sprintf("%v%v", acifile, ".asc") //TODO: only for testing,pubkey will be read and saved via user management module pubkeyspath := module.GetPubkeysPath(namespace, repository, setting.APIVERSION_ACI) if _, err := os.Stat(pubkeyspath); err != nil { if err := os.MkdirAll(pubkeyspath, os.ModePerm); err != nil { log.Error("[ACI API] Failed to create pubkeys path %v: %v", pubkeyspath, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to create pubkeys path"}) return http.StatusInternalServerError, result } } imageId := utils.MD5(uuid.NewV4().String()) imagepath := module.GetImagePath(imageId, setting.APIVERSION_ACI) if err := os.MkdirAll(imagepath, os.ModePerm); err != nil { log.Error("[ACI API] Failed to create aci path %v: %v", imagepath, err.Error()) result, _ := json.Marshal(map[string]string{"message": "Failed to create aci path"}) return http.StatusInternalServerError, result } prefix := fmt.Sprintf("%v://%v/ac/push/%v/%v/", setting.ListenMode, setting.Domains, namespace, repository) endpoint := models.UploadDetails{ ACIPushVersion: "0.0.1", //TODO: follow ACI push spec Multipart: false, ManifestURL: prefix + imageId + "/manifest", SignatureURL: prefix + imageId + "/signature/" + signfile, ACIURL: prefix + imageId + "/aci/" + acifile, CompletedURL: prefix + imageId + "/complete/" + acifile + "/" + signfile, } result, _ := json.Marshal(endpoint) return http.StatusOK, result }