예제 #1
0
// Init create directory and setup the cache location
func (ucc *UpdateClientConfig) Init() error {
	homeDir := os.Getenv("HOME")
	if homeDir == "" {
		return errors.New("Cannot get home directory")
	}

	topPath := filepath.Join(homeDir, topDir)
	if !utils.IsDirExist(topPath) {
		if err := os.MkdirAll(topPath, os.ModePerm); err != nil {
			return err
		}
	}

	cachePath := filepath.Join(homeDir, topDir, cacheDir)
	if !utils.IsDirExist(cachePath) {
		if err := os.MkdirAll(cachePath, os.ModePerm); err != nil {
			return err
		}
	}

	if !ucc.exist() {
		return ucc.save()
	}
	return nil
}
예제 #2
0
func SaveLayerLocal(srcPath, srcFile, dstPath, dstFile string, reqbody []byte) (int, error) {
	if !utils.IsDirExist(dstPath) {
		os.MkdirAll(dstPath, os.ModePerm)
	}

	if utils.IsFileExist(dstFile) {
		os.Remove(dstFile)
	}

	var data []byte
	if _, err := os.Stat(srcFile); err == nil {
		data, _ = ioutil.ReadFile(srcFile)
		if err := ioutil.WriteFile(dstFile, data, 0777); err != nil {
			return 0, err
		}
		os.RemoveAll(srcPath)
	} else {
		data = reqbody
		if err := ioutil.WriteFile(dstFile, data, 0777); err != nil {
			return 0, err
		}
	}

	return len(data), nil
}
예제 #3
0
func PutImageLayerv1Handler(ctx *macaron.Context, log *logs.BeeLogger) (int, []byte) {
	imageId := ctx.Params(":imageId")

	basePath := setting.ImagePath
	imagePath := fmt.Sprintf("%v/images/%v", basePath, imageId)
	layerfile := fmt.Sprintf("%v/images/%v/layer", basePath, imageId)

	if !utils.IsDirExist(imagePath) {
		os.MkdirAll(imagePath, os.ModePerm)
	}

	if _, err := os.Stat(layerfile); err == nil {
		os.Remove(layerfile)
	}

	data, _ := ctx.Req.Body().Bytes()
	if err := ioutil.WriteFile(layerfile, data, 0777); err != nil {
		log.Error("[REGISTRY API V1] Failed to save image layer: %v", err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Failed to save image layer"})
		return http.StatusBadRequest, result
	}

	i := new(models.Image)
	if err := i.PutLayer(imageId, layerfile, true, int64(len(data))); err != nil {
		log.Error("[REGISTRY API V1] Failed to save image %v layer data: %v", imageId, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Failed to save image layer data"})
		return http.StatusBadRequest, result
	}

	result, _ := json.Marshal(map[string]string{})
	return http.StatusOK, result
}
예제 #4
0
// SetKM sets the keymanager
func (r *LocalRepo) SetKM(kmURL string) error {
	// pull the public key
	k, err := km.NewKeyManager(kmURL)
	if err != nil {
		return err
	}

	data, err := k.GetPublicKey(r.Proto, r.Namespace)
	if err != nil {
		return err
	}

	keyfile := r.GetPublicKeyFile()
	if !utils.IsDirExist(filepath.Dir(keyfile)) {
		if err := os.MkdirAll(filepath.Dir(keyfile), 0755); err != nil {
			return err
		}
	}
	if err := ioutil.WriteFile(keyfile, data, 0644); err != nil {
		return err
	}

	r.kmURL = kmURL
	return nil
}
예제 #5
0
func (uc *UpdateClient) save(repo client.UpdateClientRepo, file string, bytes []byte) (string, error) {
	localFile := filepath.Join(uc.getCacheDir(), repo.NRString(), file)
	if !utils.IsDirExist(filepath.Dir(localFile)) {
		os.MkdirAll(filepath.Dir(localFile), 0755)
	}

	err := ioutil.WriteFile(localFile, bytes, 0644)
	if err != nil {
		return "", err
	}

	return localFile, nil
}
예제 #6
0
//PatchBlobsV2Handler is
//Upload a chunk of data for the specified upload.
//Docker 1.9.x above version saves layer in PATCH methord
//Docker 1.9.x below version saves layer in PUT methord
func PatchBlobsV2Handler(ctx *macaron.Context) (int, []byte) {
	repository := ctx.Params(":repository")
	namespace := ctx.Params(":namespace")

	desc := ctx.Params(":uuid")
	uuid := strings.Split(desc, "?")[0]

	if upload, err := module.CheckDockerVersion19(ctx.Req.Header.Get("User-Agent")); err != nil {
		log.Errorf("Decode docker version error: %s", err.Error())

		result, _ := module.EncodingError(module.BLOB_UPLOAD_UNKNOWN, map[string]string{"namespace": namespace, "repository": repository})
		return http.StatusBadRequest, result
	} else if upload == true {
		//It's run above docker 1.9.0
		basePath := setting.DockerV2Storage
		uuidPath := fmt.Sprintf("%s/uuid/%s", basePath, uuid)
		uuidFile := fmt.Sprintf("%s/uuid/%s/%s", basePath, uuid, uuid)

		if !utils.IsDirExist(uuidPath) {
			os.MkdirAll(uuidPath, os.ModePerm)
		}

		if _, err := os.Stat(uuidFile); err == nil {
			os.Remove(uuidFile)
		}

		if file, err := os.Create(uuidFile); err != nil {
			log.Errorf("[%s] Create UUID file error: %s", ctx.Req.RequestURI, err.Error())

			result, _ := module.EncodingError(module.BLOB_UPLOAD_UNKNOWN, map[string]string{"namespace": namespace, "repository": repository})
			return http.StatusBadRequest, result
		} else {
			io.Copy(file, ctx.Req.Request.Body)

			size, _ := utils.GetFileSize(uuidFile)

			ctx.Resp.Header().Set("Range", fmt.Sprintf("0-%v", size-1))
		}
	}

	state := utils.MD5(fmt.Sprintf("%s/%v", fmt.Sprintf("%s/%s", namespace, repository), time.Now().UnixNano()/int64(time.Millisecond)))
	random := fmt.Sprintf("https://%s/v2/%s/%s/blobs/uploads/%s?_state=%s",
		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)

	result, _ := json.Marshal(map[string]string{})
	return http.StatusOK, result
}
예제 #7
0
//AppcPutACIV1Handler is
func AppcPutACIV1Handler(ctx *macaron.Context) (int, []byte) {
	namespace := ctx.Params(":namespace")
	repository := ctx.Params(":repository")
	version := ctx.Params(":version")
	aci := ctx.Params(":aci")

	r := new(models.AppcV1)
	if err := r.Get(namespace, repository); err != nil {
		log.Errorf("[%s] get AppcV1 repository error: %s", ctx.Req.RequestURI, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Get Appc Repository Error."})
		return http.StatusBadRequest, result
	}

	basePath := setting.AppcStorage
	imagePath := fmt.Sprintf("%s/%s/%s/%s", basePath, namespace, repository, version)
	filePath := fmt.Sprintf("%s/%s", imagePath, aci)

	if !utils.IsDirExist(imagePath) {
		os.MkdirAll(imagePath, os.ModePerm)
	}

	if _, err := os.Stat(filePath); err == nil {
		os.Remove(filePath)
	}

	if file, err := os.Create(filePath); err != nil {
		log.Errorf("[%s] Create aci file error: %s", ctx.Req.RequestURI, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Create .aci File Error."})
		return http.StatusBadRequest, result
	} else {
		io.Copy(file, ctx.Req.Request.Body)
	}

	size, _ := utils.GetFileSize(filePath)

	i := new(models.ACIv1)
	if err := i.PutACI(r.ID, size, version, aci, filePath); err != nil {
		log.Errorf("[%s] write aci data error: %s", ctx.Req.RequestURI, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Write .aci Data Error."})
		return http.StatusBadRequest, result
	}

	result, _ := json.Marshal(map[string]string{})
	return http.StatusOK, result
}
예제 #8
0
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
}
예제 #9
0
//PutImageLayerV1Handler is save image layer file in the server.
func PutImageLayerV1Handler(ctx *macaron.Context) (int, []byte) {
	//TODO: If standalone == true, Dockyard will check HEADER Authorization; if standalone == false, Dockyard will check HEADER TOEKN.
	imageID := ctx.Params(":image")

	basePath := setting.DockerV1Storage
	imagePath := fmt.Sprintf("%s/images/%s", basePath, imageID)
	layerfile := fmt.Sprintf("%s/images/%s/%s", basePath, imageID, imageID)

	if !utils.IsDirExist(imagePath) {
		os.MkdirAll(imagePath, os.ModePerm)
	}

	if _, err := os.Stat(layerfile); err == nil {
		os.Remove(layerfile)
	}

	if file, err := os.Create(layerfile); err != nil {
		log.Errorf("[%s] Create image file error: %s", ctx.Req.RequestURI, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Write Image File Error."})
		return http.StatusBadRequest, result
	} else {
		io.Copy(file, ctx.Req.Request.Body)
	}

	size, _ := utils.GetFileSize(layerfile)

	image := new(models.DockerImageV1)
	if err := image.PutLayer(imageID, layerfile, size); err != nil {
		log.Errorf("[%s] Failed to save image layer data error: %s", ctx.Req.RequestURI, err.Error())

		result, _ := json.Marshal(map[string]string{"message": "Put Image Layer Data Error"})
		return http.StatusBadRequest, result
	}

	result, _ := json.Marshal(map[string]string{})
	return http.StatusOK, result
}
예제 #10
0
func generateKey(keyDir string) error {
	privBytes, pubBytes, err := utils.GenerateRSAKeyPair(defaultBitsSize)
	if err != nil {
		return err
	}

	if !utils.IsDirExist(keyDir) {
		err := os.MkdirAll(keyDir, 0755)
		if err != nil {
			return err
		}
	}

	if err := ioutil.WriteFile(filepath.Join(keyDir, defaultPrivateKey), privBytes, 0600); err != nil {
		return err
	}

	if err := ioutil.WriteFile(filepath.Join(keyDir, defaultPublicKey), pubBytes, 0644); err != nil {
		return err
	}

	return nil
}
예제 #11
0
// NewLocalRepo gets repo by a proto, a local storage path and a url
// nr : "namespace/repository" or just 'namespace'
func NewLocalRepo(path string, proto string, nr string) (LocalRepo, error) {
	repo := LocalRepo{Proto: proto, Path: path}
	parts := strings.Split(nr, "/")
	if nr != "" && len(parts) == 1 {
		repo.Namespace = nr
	} else if len(parts) == 2 {
		repo.Namespace = parts[0]
		repo.LocalRepository = parts[1]
	} else {
		return LocalRepo{}, ErrorInvalidLocalLocalRepo
	}

	// create top dir if not exist
	topDir := repo.GetTopDir()
	if !utils.IsDirExist(topDir) {
		if err := os.MkdirAll(topDir, 0777); err != nil {
			return LocalRepo{}, err
		}
	}

	repo.kmURL = ""
	return repo, nil
}
예제 #12
0
//PutBlobsV2Handler is
//Complete the upload specified by uuid, optionally appending the body as the final chunk.
func PutBlobsV2Handler(ctx *macaron.Context) (int, []byte) {
	var size int64

	repository := ctx.Params(":repository")
	namespace := ctx.Params(":namespace")

	desc := ctx.Params(":uuid")
	uuid := strings.Split(desc, "?")[0]

	digest := ctx.Query("digest")
	tarsum := strings.Split(digest, ":")[1]

	basePath := setting.DockerV2Storage
	imagePath := fmt.Sprintf("%s/image/%s", basePath, tarsum)
	imageFile := fmt.Sprintf("%s/image/%s/%s", basePath, tarsum, tarsum)

	//Save from uuid path save too image path
	if !utils.IsDirExist(imagePath) {
		os.MkdirAll(imagePath, os.ModePerm)
	}

	if _, err := os.Stat(imageFile); err == nil {
		os.Remove(imageFile)
	}

	if upload, err := module.CheckDockerVersion19(ctx.Req.Header.Get("User-Agent")); err != nil {
		log.Errorf("Decode docker version error: %s", err.Error())

		result, _ := module.EncodingError(module.BLOB_UPLOAD_INVALID, map[string]string{"namespace": namespace, "repository": repository})
		return http.StatusBadRequest, result
	} else if upload == true {
		//Docker 1.9.x above version saves layer in PATCH method, in PUT method move from uuid to image:sha256
		uuidPath := fmt.Sprintf("%s/uuid/%s", basePath, uuid)
		uuidFile := fmt.Sprintf("%s/uuid/%s/%s", basePath, uuid, uuid)

		if _, err := os.Stat(uuidFile); err == nil {
			if err := os.Rename(uuidFile, imageFile); err != nil {
				log.Errorf("Move the temp file to image folder %s error: %s", imageFile, err.Error())

				result, _ := module.EncodingError(module.BLOB_UPLOAD_INVALID, map[string]string{"namespace": namespace, "repository": repository})
				return http.StatusBadRequest, result
			}

			size, _ = utils.GetFileSize(imagePath)

			os.RemoveAll(uuidFile)
			os.RemoveAll(uuidPath)
		}
	} else if upload == false {
		//Docker 1.9.x below version saves layer in PUT methord, save data to file directly.
		if file, err := os.Create(imageFile); err != nil {
			log.Errorf("Save the file %s error: %s", imageFile, err.Error())

			result, _ := module.EncodingError(module.BLOB_UPLOAD_INVALID, map[string]string{"namespace": namespace, "repository": repository})
			return http.StatusBadRequest, result
		} else {
			io.Copy(file, ctx.Req.Request.Body)
			size, _ = utils.GetFileSize(imagePath)
		}
	}

	i := new(models.DockerImageV2)
	if err := i.Put(tarsum, imageFile, size); err != nil {
		log.Errorf("Save the iamge data %s error: %s", tarsum, err.Error())

		result, _ := module.EncodingError(module.BLOB_UPLOAD_INVALID, map[string]string{"namespace": namespace, "repository": repository})
		return http.StatusBadRequest, result
	}

	state := utils.MD5(fmt.Sprintf("%s/%v", fmt.Sprintf("%s/%s", namespace, repository), time.Now().UnixNano()/int64(time.Millisecond)))
	random := fmt.Sprintf("https://%s/v2/%s/%s/blobs/uploads/%s?_state=%s",
		setting.Domains, namespace, repository, uuid, state)

	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.StatusOK, result
}
예제 #13
0
// Put adds an application to a repository
func (r LocalRepo) Put(name string, content []byte, method utils.EncryptMethod) (string, error) {
	topDir := r.GetTopDir()
	if !utils.IsDirExist(topDir) {
		if err := os.MkdirAll(topDir, 0777); err != nil {
			return "", err
		}
	}

	var meta utils.Meta
	metaFile := r.GetMetaFile()
	if utils.IsFileExist(metaFile) {
		data, err := ioutil.ReadFile(metaFile)
		if err != nil {
			return "", err
		}

		err = json.Unmarshal(data, &meta)
		if err != nil {
			//This may happend in migration, meta struct changes.
			os.Remove(metaFile)
		}

	}

	encryptContent, err := r.encrypt(method, content)
	if err != nil {
		return "", err
	}

	item := utils.GenerateMetaItem(name, encryptContent)
	item.SetEncryption(method)

	// Using the 'hash' value to rename the original file
	dataFileName := item.GetHash()
	dataFile := filepath.Join(topDir, defaultTargetDir, dataFileName)
	if !utils.IsDirExist(filepath.Dir(dataFile)) {
		if err := os.MkdirAll(filepath.Dir(dataFile), 0777); err != nil {
			return "", err
		}
	}

	// write data
	if err := ioutil.WriteFile(dataFile, encryptContent, 0644); err != nil {
		return "", err
	}

	// get meta content
	exist := false
	for i := range meta.Items {
		if meta.Items[i].Name == name {
			meta.Items[i] = item
			exist = true
		}
	}
	if !exist {
		meta.Items = append(meta.Items, item)
	}

	// write meta data
	err = r.saveMeta(meta)
	if err != nil {
		os.Remove(dataFile)
		return "", err
	}

	return dataFile, nil
}