return index on get magifest

This commit is contained in:
2026-02-23 18:38:45 +02:00
parent 96b24c6b63
commit 5ec5592a13
8 changed files with 156 additions and 61 deletions
+2 -2
View File
@@ -33,9 +33,9 @@ func TestFile(t *testing.T) {
err = db.InitDatabase()
require.NoError(t, err)
id := uuid.NewUUID()
id := auxuuid.NewUUID()
timenow := auxtool.TimeNow()
creator := uuid.NewUUID()
creator := auxuuid.NewUUID()
collection := "foo"
newFile := &descr.File{
ID: id,
+3 -3
View File
@@ -34,10 +34,10 @@ func TestGrant(t *testing.T) {
err = db.InitDatabase()
require.NoError(t, err)
id := uuid.NewUUID()
accountID := uuid.NewUUID()
id := auxuuid.NewUUID()
accountID := auxuuid.NewUUID()
timenow := auxtool.TimeNow()
creator := uuid.NewUUID()
creator := auxuuid.NewUUID()
newGrant := &descr.Grant{
ID: id,
AccountID: accountID,
+39 -16
View File
@@ -19,12 +19,13 @@ func (db *Database) InsertManifest(ctx context.Context, manifest *descr.Manifest
var err error
var request string
request = `INSERT INTO manifests(id, name, reference, contentType, payload, digest,
created_at, updated_at, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
created_at, updated_at, created_by, updated_by, architecture, os, variant)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
_, err = db.db.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
manifest.ContentType, manifest.Payload, manifest.Digest,
manifest.CreatedAt, manifest.UpdatedAt,
manifest.CreatedBy, manifest.UpdatedBy)
manifest.CreatedBy, manifest.UpdatedBy,
manifest.Architecture, manifest.OS, manifest.Variant)
if err != nil {
return err
}
@@ -39,12 +40,14 @@ func (db *Database) InsertManifests(ctx context.Context, manifests []*descr.Mani
for _, manifest := range manifests {
var request string
request = `INSERT INTO manifests(id, name, reference, contentType, payload, digest,
created_at, updated_at, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`
created_at, updated_at, created_by, updated_by,
architecture, os, variant)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`
_, err = tx.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
manifest.ContentType, manifest.Payload, manifest.Digest,
manifest.CreatedAt, manifest.UpdatedAt,
manifest.CreatedBy, manifest.UpdatedBy)
manifest.CreatedBy, manifest.UpdatedBy,
manifest.Architecture, manifest.OS, manifest.Variant)
if err != nil {
return err
}
@@ -62,9 +65,10 @@ func (db *Database) UpdateManifest(ctx context.Context, manifest *descr.Manifest
var request string
// Manifest
request = `UPDATE manifests SET contentType = $1, payload = $2, digest = $3, updated_at = $4
WHERE name = $5 AND reference = $6`
WHERE name = $5 AND reference = $6, architecture = $7, os = $8, variant = $9`
_, err = db.db.Exec(request, manifest.ContentType, manifest.Payload, manifest.Digest,
manifest.UpdatedAt, manifest.Name, manifest.Reference)
manifest.UpdatedAt, manifest.Name, manifest.Reference,
manifest.Architecture, manifest.OS, manifest.Variant)
if err != nil {
return err
}
@@ -80,12 +84,13 @@ func (db *Database) InsertManifestWithLayers(ctx context.Context, manifest *desc
// Manifest
request = `
INSERT INTO manifests(id, name, reference, contentType, payload, digest,
created_at, updated_at, created_by, updated_by)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);`
created_at, updated_at, created_by, updated_by, architecture, os, variant)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13);`
_, err = tx.Exec(request, manifest.ID, manifest.Name, manifest.Reference,
manifest.ContentType, manifest.Payload, manifest.Digest,
manifest.CreatedAt, manifest.UpdatedAt,
manifest.CreatedBy, manifest.UpdatedBy)
manifest.CreatedBy, manifest.UpdatedBy,
manifest.Architecture, manifest.OS, manifest.Variant)
if err != nil {
return err
}
@@ -124,10 +129,11 @@ func (db *Database) UpdateManifestWithBlobs(ctx context.Context, manifest *descr
// Manifest
request = `UPDATE manifests SET contentType = $1, payload = $2, digest = $3, updated_at = $4, updated_by = $5
WHERE name = $6 AND reference = $7`
WHERE name = $6 AND reference = $7, architecture = $8, os = $9, variant = $10`
_, err = tx.Exec(request, manifest.ContentType, manifest.Payload, manifest.Digest,
manifest.UpdatedAt, manifest.UpdatedBy,
manifest.Name, manifest.Reference)
manifest.Name, manifest.Reference,
manifest.Architecture, manifest.OS, manifest.Variant)
if err != nil {
return err
}
@@ -202,20 +208,37 @@ func (db *Database) GetManifestByDigest(ctx context.Context, name, digest string
return exists, manifest, err
}
func (db *Database) GetManifestByReference(ctx context.Context, name, reference string) (bool, descr.Manifest, error) {
func (db *Database) GetManifestsByReference(ctx context.Context, name, reference string) (bool, []descr.Manifest, error) {
var err error
manifest := descr.Manifest{}
exists := false
manifests := make([]descr.Manifest, 0)
request := `SELECT * FROM manifests WHERE name = $1 AND reference = $2 LIMIT 1`
err = db.db.Select(&manifests, request, name, reference)
if err != nil {
return exists, manifest, err
return exists, manifests, err
}
if len(manifests) > 0 {
exists = true
}
return exists, manifests, err
}
func (db *Database) GetManifestsByReferenceArchitecture(ctx context.Context, name, reference, architecture, os, variant string) (bool, descr.Manifest, error) {
var err error
exists := false
manifest := descr.Manifest{}
manifests := make([]descr.Manifest, 0)
request := `SELECT * FROM manifests WHERE name = $1 AND reference = $2
AND architecture = $3 AND os = $4 AND variant = $5 LIMIT 1000`
err = db.db.Select(&manifests, request, name, reference, architecture, os, variant)
if err != nil {
return exists, manifest, err
}
if len(manifests) > 0 {
manifest = manifests[0]
exists = true
}
return exists, manifest, err
}
+14 -11
View File
@@ -27,19 +27,22 @@ const schema = `
--- DROP TABLE IF EXISTS manifests;
CREATE TABLE IF NOT EXISTS manifests (
id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
reference VARCHAR(255) NOT NULL,
digest VARCHAR(1024) NOT NULL,
contentType VARCHAR(255) NOT NULL,
payload VARCHAR(4096) NOT NULL,
created_at VARCHAR(255) NOT NULL,
updated_at VARCHAR(255) NOT NULL,
created_by VARCHAR(255) NOT NULL,
updated_by VARCHAR(255) NOT NULL
id VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
reference VARCHAR(255) NOT NULL,
digest VARCHAR(1024) NOT NULL,
contentType VARCHAR(255) NOT NULL,
payload VARCHAR(4096) NOT NULL,
created_at VARCHAR(255) NOT NULL,
updated_at VARCHAR(255) NOT NULL,
created_by VARCHAR(255) NOT NULL,
updated_by VARCHAR(255) NOT NULL,
architecture VARCHAR(255) NOT NULL,
os VARCHAR(255) NOT NULL,
variant VARCHAR(255) NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS manifests_index
ON manifests(name, reference);
ON manifests(name, reference, architecture, os, variant);
CREATE TABLE IF NOT EXISTS blobs (
id VARCHAR(255) NOT NULL,
+41 -19
View File
@@ -48,6 +48,7 @@ func (oper *Operator) ManifestExists(ctx context.Context, params *ManifestExists
}
var manifest descr.Manifest
manifests := make([]descr.Manifest, 0)
var exists bool
if stringLikeSHA256Digest(params.Reference) {
digest := fmt.Sprintf("%s:%s", sha256prefix, params.Reference)
@@ -59,13 +60,14 @@ func (oper *Operator) ManifestExists(ctx context.Context, params *ManifestExists
return res, http.StatusNotFound, err
}
} else {
exists, manifest, err = oper.mdb.GetManifestByReference(ctx, params.Name, params.Reference)
exists, manifests, err = oper.mdb.GetManifestsByReference(ctx, params.Name, params.Reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
if !exists {
return res, http.StatusNotFound, err
}
manifest = manifests[0] // TODO: tmp
}
digest := auxoci.SHA256DigestFromString(manifest.Payload)
@@ -169,14 +171,17 @@ func (oper *Operator) PutManifest(ctx context.Context, params *PutManifestParams
incomingManifest.MediaType = params.ContentType
}
manifestExists, existengManifestDescr, err := oper.mdb.GetManifestByReference(ctx, params.Name, params.Reference)
name := params.Name
reference := params.Reference
arch := incomingManifest.Subject.Platform.Architecture
os := incomingManifest.Subject.Platform.OS
variant := incomingManifest.Subject.Platform.Variant
manifestExists, existengManifestDescr, err := oper.mdb.GetManifestsByReferenceArchitecture(ctx, name, reference, arch, os, variant)
if err != nil {
return res, http.StatusInternalServerError, err
}
name := params.Name
reference := params.Reference
incomingManifestDescr, incomingLayerDescrs, err := descrsFromManifest(name, reference, incomingManifest, incomingManifestBytes)
// Always check layer files for availability
var blobError error
@@ -297,23 +302,33 @@ func (oper *Operator) GetManifest(ctx context.Context, params *GetManifestParams
if !exists {
return res, http.StatusNotFound, err
}
manifestDigest := auxoci.SHA256DigestFromString(manifestDescr.Payload)
res.DockerContentDigest = manifestDigest.String()
res.ContentLength = strconv.FormatInt(int64(len(manifestDescr.Payload)), 10)
res.ContentType = manifestDescr.ContentType
res.Payload = manifestDescr.Payload
} else {
exists, manifestDescr, err = oper.mdb.GetManifestByReference(ctx, params.Name, params.Reference)
exists, manifestDescrs, err := oper.mdb.GetManifestsByReference(ctx, params.Name, params.Reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
if !exists {
return res, http.StatusNotFound, err
}
index, indexBytes, err := indexFromManigestDescrs(manifestDescrs)
if err != nil {
return res, http.StatusInternalServerError, err
}
indexDigest := auxoci.SHA256DigestFromString(indexBytes)
res.DockerContentDigest = indexDigest.String()
res.ContentLength = strconv.FormatInt(int64(len(indexBytes)), 10)
res.ContentType = index.MediaType
res.Payload = string(indexBytes)
}
manifestDigest := auxoci.SHA256DigestFromString(manifestDescr.Payload)
res.DockerContentDigest = manifestDigest.String()
res.ContentLength = strconv.FormatInt(int64(len(manifestDescr.Payload)), 10)
res.ContentType = manifestDescr.ContentType
res.Payload = manifestDescr.Payload
return res, http.StatusOK, err
}
@@ -352,9 +367,13 @@ func (oper *Operator) DeleteManifest(ctx context.Context, params *DeleteManifest
return res, http.StatusNotFound, err
}
reference = manifestDescr.Reference
err = oper.deleteManifestObjects(ctx, params.Name, reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
} else {
// Check manifest by name and reference
exists, manifestDescr, err = oper.mdb.GetManifestByReference(ctx, params.Name, params.Reference)
exists, manifestDescrs, err := oper.mdb.GetManifestsByReference(ctx, params.Name, params.Reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
@@ -362,12 +381,15 @@ func (oper *Operator) DeleteManifest(ctx context.Context, params *DeleteManifest
return res, http.StatusNotFound, err
}
reference = params.Reference
for _, manifestDescr := range manifestDescrs {
reference = manifestDescr.Reference
err = oper.deleteManifestObjects(ctx, params.Name, reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
}
}
// Get blobs associated with the name
err = oper.deleteManifestObjects(ctx, params.Name, reference)
if err != nil {
return res, http.StatusInternalServerError, err
}
return res, http.StatusAccepted, err
}
+39
View File
@@ -10,6 +10,9 @@
package operator
import (
"encoding/json"
"mstore/pkg/auxoci"
"mstore/pkg/auxtool"
"mstore/pkg/auxuuid"
"mstore/pkg/descr"
@@ -18,6 +21,42 @@ import (
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func indexFromManigestDescrs(manifestDescrs []descr.Manifest) (ocispec.Index, string, error) {
var err error
var payload string
index := ocispec.Index{
MediaType: ocispec.MediaTypeImageIndex,
Manifests: make([]ocispec.Descriptor, 0),
}
index.Versioned.SchemaVersion = 2
for _, manifestDescr := range manifestDescrs {
var ociManifest ocispec.Manifest
ociManifest.Subject = &ocispec.Descriptor{}
ociManifest.Subject.Platform = &ocispec.Platform{}
ociManifest.Config = ocispec.Descriptor{}
ociManifest.Config.Platform = &ocispec.Platform{}
err = json.Unmarshal([]byte(manifestDescr.Payload), &ociManifest)
if err != nil {
return index, payload, err
}
descriptor := ocispec.Descriptor{
MediaType: ocispec.MediaTypeImageManifest,
Digest: auxoci.SHA256DigestFromString(manifestDescr.Payload),
Size: int64(len(manifestDescr.Payload)),
Platform: ociManifest.Subject.Platform,
}
index.Manifests = append(index.Manifests, descriptor)
}
indexBytes, err := json.Marshal(index)
if err != nil {
return index, payload, err
}
payload = string(indexBytes)
return index, payload, err
}
func descrsFromManifest(name, reference string, manifest *ocispec.Manifest, rawManifest []byte) (descr.Manifest, []descr.Blob, error) {
var err error
manifestDescr := descr.Manifest{}