working commit

This commit is contained in:
2026-03-11 19:47:40 +02:00
parent a81334aedf
commit a064d942e7
56 changed files with 564 additions and 243 deletions
+31 -34
View File
@@ -12,13 +12,14 @@ package imageoper
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strconv"
"mstore/pkg/auxoci"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
type PutManifestParams struct {
@@ -53,14 +54,8 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
err = fmt.Errorf("Empty name")
return res, http.StatusBadRequest, err
}
// Check Content-Type
var mimeIsAcceptably bool
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == oimMimeType
mimeIsAcceptably = mimeIsAcceptably || params.ContentType == ddmMimeType
//mimeIsAcceptably = mimeIsAcceptably || params.ContentType == oicMimeType
//mimeIsAcceptably = mimeIsAcceptably || params.ContentType == dciMimeType
if !mimeIsAcceptably {
if params.ContentType != oimMimeType && params.ContentType != ddmMimeType {
err = fmt.Errorf("Unknown or empty Content-Type: %s", params.ContentType)
return res, http.StatusNotFound, err
}
@@ -86,47 +81,48 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
if err != nil {
return res, http.StatusInternalServerError, err
}
incomingManifestBytes := buffer.Bytes()
if int64(len(incomingManifestBytes)) != contentLength {
inManData := buffer.Bytes()
if int64(len(inManData)) != contentLength {
err = fmt.Errorf("Mismatch Content-Length and received manifest size: %d vs %d",
contentLength, len(incomingManifestBytes))
contentLength, len(inManData))
code := http.StatusInternalServerError
return res, code, err
}
if len(incomingManifestBytes) > (4 * 1024 * 1024) {
err = fmt.Errorf("Payload more 4M: %d bytes", len(incomingManifestBytes))
if len(inManData) > (4 * 1024 * 1024) {
err = fmt.Errorf("Payload more 4M: %d bytes", len(inManData))
code := http.StatusRequestEntityTooLarge
return res, code, err
}
incomingManifest, err := auxoci.ParseOCIManifest(incomingManifestBytes)
inMan := &ocispec.Manifest{}
err = json.Unmarshal(inManData, inMan)
if err != nil {
err = fmt.Errorf("Parsing OCI manifest error: %v", err)
err = fmt.Errorf("Manifest parsing error: %v", err)
return res, http.StatusInternalServerError, err
}
if incomingManifest.MediaType == "" {
incomingManifest.MediaType = params.ContentType
if inMan.MediaType == "" {
inMan.MediaType = params.ContentType
}
name := params.Name
reference := params.Reference
arch := incomingManifest.Subject.Platform.Architecture
os := incomingManifest.Subject.Platform.OS
variant := incomingManifest.Subject.Platform.Variant
if inMan.Subject == nil {
}
manifestExists, existingManifestDescr, err := oper.mdb.GetManifestsByReferenceArchitecture(ctx, name, reference, arch, os, variant)
arch := inMan.Subject.Platform.Architecture
os := inMan.Subject.Platform.OS
variant := inMan.Subject.Platform.Variant
manexist, exMandescr, err := oper.mdb.GetManifestsByReferenceArchitecture(ctx, name, reference, arch, os, variant)
if err != nil {
return res, http.StatusInternalServerError, err
}
incomingManifestDescr, incomingLayerDescrs, err := descrsFromManifest(name, reference, incomingManifest, incomingManifestBytes)
inManDescr, inlayerdescrs, err := descrsFromManifest(name, reference, inMan, inManData)
// Always check layer files for availability
var blobError error
for _, blobDescr := range incomingLayerDescrs {
for _, blobDescr := range inlayerdescrs {
blobExists, _, err := oper.store.BlobExists(blobDescr.Digest)
if err != nil {
return res, http.StatusInternalServerError, err
@@ -141,32 +137,33 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
// TODO: more relevant code?
return res, http.StatusFailedDependency, blobError
}
if !manifestExists {
if !manexist {
// Store manifest and layesrs data
err = oper.mdb.InsertManifestWithLayers(ctx, &incomingManifestDescr, incomingLayerDescrs)
err = oper.mdb.InsertManifestWithLayers(ctx, &inManDescr, inlayerdescrs)
if err != nil {
return res, http.StatusInternalServerError, err
}
} else {
/* TODO: only update descr
if bytes.Equal(existingManifestBytes, incomingManifestBytes) {
if bytes.Equal(exManData, inManData) {
return res, http.StatusCreated, err
}
*/
existingManifestBytes := []byte(existingManifestDescr.Payload)
existingManifest, err := auxoci.ParseOCIManifest(existingManifestBytes)
exManData := []byte(exMandescr.Payload)
exMan := &ocispec.Manifest{}
err := json.Unmarshal(exManData, exMan)
if err != nil {
return res, http.StatusInternalServerError, err
}
addedBlobDescrs, uselessBlobDescrs, err := layersDiff(name, reference,
existingManifest, incomingManifest, incomingManifestBytes)
exMan, inMan, inManData)
if err != nil {
return res, http.StatusInternalServerError, err
}
// Starting manifest and blobs transaction
err = oper.mdb.UpdateManifestWithBlobs(ctx, &incomingManifestDescr, addedBlobDescrs, uselessBlobDescrs)
err = oper.mdb.UpdateManifestWithBlobs(ctx, &inManDescr, addedBlobDescrs, uselessBlobDescrs)
if err != nil {
return res, http.StatusInternalServerError, err
}
@@ -190,7 +187,7 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
}
}
for _, blobDescr := range incomingLayerDescrs {
for _, blobDescr := range inlayerdescrs {
// TODO: move the requests to db layer transaction
blobDescrExists, _, err := oper.mdb.GetBlobByNameDigest(ctx, blobDescr.Name, blobDescr.Digest)
if err != nil {