Beispiel #1
0
func (ctx *Context) PutImageLayerHandler(w http.ResponseWriter, r *http.Request) {
	imageId := mux.Vars(r)["imageId"]
	jsonData, err := ctx.storage.GetContent(storage.ImageJsonPath(imageId))
	if err != nil {
		sendResponse(w, "Image's JSON not found", 404, nil, false)
		return
	}

	checksum, err := ctx.storage.GetContent(storage.ImageChecksumPath(imageId))
	if err != nil {
		sendResponse(w, "Image's checksum not found", 404, nil, false)
		return
	}

	layerPath := storage.ImageLayerPath(imageId)
	markPath := storage.ImageMarkPath(imageId)

	if layerExists, err := ctx.storage.Exists(layerPath); layerExists == true && err == nil {
		if markExists, err := ctx.storage.Exists(markPath); markExists == false || err != nil {
			sendResponse(w, "Image already exists", 409, nil, false)
			return
		}
	}

	writer, err := ctx.storage.StreamWrite(layerPath)
	if err != nil {
		sendResponse(w, "Couldn't write to layer file", 500, nil, false)
		return
	}

	io.Copy(writer, r.Body)

	checksumParts := strings.Split(string(checksum), ":")
	computedChecksum, err := ctx.computeImageChecksum(checksumParts[0], imageId, jsonData)
	if err != nil || computedChecksum != strings.ToLower(checksumParts[1]) {
		sendResponse(w, "Checksum mismatch, ignoring the layer", 400, nil, false)
		return
	}

	ctx.storage.Remove(markPath)

	sendResponse(w, nil, http.StatusOK, nil, false)
}
Beispiel #2
0
func (ctx *Context) PutImageJsonHandler(w http.ResponseWriter, r *http.Request) {
	imageId := mux.Vars(r)["imageId"]
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		sendResponse(w, "Couldn't read request body", 500, nil, false)
		return
	}

	var data map[string]string
	if err := json.Unmarshal(body, &data); err != nil {
		sendResponse(w, "Invalid JSON", 400, nil, false)
		return
	}

	if _, ok := data["id"]; !ok {
		sendResponse(w, "Missing Key `id' in JSON", 400, nil, false)
		return
	}

	checksum := r.Header.Get("X-Docker-Checksum")
	if checksum == "" {
		sendResponse(w, "Missing Image's checksum", 400, nil, false)
		return
	}

	checksumParts := strings.Split(string(checksum), ":")
	if len(checksumParts) != 2 {
		sendResponse(w, "Invalid checksum format", 400, nil, false)
		return
	}

	if checksumParts[0] != "sha256" {
		sendResponse(w, "Checksum algorithm not supported", 400, nil, false)
		return
	}

	checksumPath := storage.ImageChecksumPath(imageId)
	ctx.storage.PutContent(checksumPath, []byte(checksum))

	if imageId != data["id"] {
		sendResponse(w, "JSON data contains invalid id", 400, nil, false)
		return
	}

	parentId, ok := data["parent"]
	exists, err := ctx.storage.Exists(storage.ImageJsonPath(parentId))
	if ok && !exists && err == nil {
		sendResponse(w, "Image depends on a non existing parent", 400, nil, false)
		return
	}

	jsonPath := storage.ImageJsonPath(imageId)
	markPath := storage.ImageMarkPath(imageId)

	jsonExists, err := ctx.storage.Exists(jsonPath)
	if err != nil {
		sendResponse(w, "Couldn't check if JSON exists", 500, nil, false)
		return
	}

	markExists, err := ctx.storage.Exists(markPath)
	if err != nil {
		sendResponse(w, "Couldn't check if mark exists", 500, nil, false)
		return
	}

	if jsonExists && !markExists {
		sendResponse(w, "Image already exists", 409, nil, false)
		return
	}

	ctx.storage.PutContent(markPath, []byte("true"))
	ctx.storage.PutContent(jsonPath, body)

	if err := ctx.generateAncestry(imageId, parentId); err != nil {
		sendResponse(w, fmt.Sprintf("Couldn't generate ancestry: %s", err), 500, nil, false)
		return
	}

	sendResponse(w, nil, 200, nil, false)
}