182 lines
4.8 KiB
Go
182 lines
4.8 KiB
Go
/*
|
|
* Copyright 2026 Oleg Borodin <onborodin@gmail.com>
|
|
*/
|
|
package imageoper
|
|
|
|
import (
|
|
"encoding/json"
|
|
|
|
//"mstore/pkg/auxoci"
|
|
"mstore/pkg/auxtool"
|
|
"mstore/pkg/auxuuid"
|
|
"mstore/pkg/descr"
|
|
|
|
ocidigest "github.com/opencontainers/go-digest"
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
func indexFromManigestDescrs(mandescrs []descr.Manifest) (ocispec.Index, []byte, error) {
|
|
var err error
|
|
var indexdata []byte
|
|
index := ocispec.Index{
|
|
MediaType: oiiMediaType,
|
|
Manifests: make([]ocispec.Descriptor, 0),
|
|
}
|
|
index.Versioned.SchemaVersion = 2
|
|
for _, mandescr := range mandescrs {
|
|
var man ocispec.Manifest
|
|
|
|
if mandescr.ContentType != oimMediaType && mandescr.ContentType != ddmMediaType {
|
|
continue
|
|
}
|
|
|
|
man.Subject = &ocispec.Descriptor{}
|
|
man.Subject.Platform = &ocispec.Platform{}
|
|
man.Config = ocispec.Descriptor{}
|
|
man.Config.Platform = &ocispec.Platform{}
|
|
|
|
err = json.Unmarshal([]byte(mandescr.Payload), &man)
|
|
if err != nil {
|
|
return index, indexdata, err
|
|
}
|
|
digobj, err := ocidigest.Parse(mandescr.Digest)
|
|
if err != nil {
|
|
return index, indexdata, err
|
|
}
|
|
size := int64(len(mandescr.Payload))
|
|
descriptor := ocispec.Descriptor{
|
|
MediaType: mandescr.ContentType,
|
|
Digest: digobj,
|
|
Size: size,
|
|
Platform: man.Subject.Platform,
|
|
}
|
|
index.Manifests = append(index.Manifests, descriptor)
|
|
}
|
|
indexdata, err = json.Marshal(index)
|
|
if err != nil {
|
|
return index, indexdata, err
|
|
}
|
|
indexdata = indexdata
|
|
return index, indexdata, err
|
|
}
|
|
|
|
func descrsFromManifest(name, reference string, manifest *ocispec.Manifest, rawManifest []byte) (descr.Manifest, []descr.Blob, error) {
|
|
var err error
|
|
mandescr := descr.Manifest{}
|
|
//configDescr := descr.Blob{}
|
|
blobDescrs := make([]descr.Blob, 0)
|
|
|
|
timestamp := auxtool.TimeNow()
|
|
|
|
// Make manifest descriptor
|
|
manifestDigest := ocidigest.SHA256.FromBytes(rawManifest).String()
|
|
mandescr = descr.Manifest{
|
|
ID: auxuuid.NewUUID(),
|
|
Name: name,
|
|
Reference: reference,
|
|
Digest: manifestDigest,
|
|
ContentType: manifest.MediaType,
|
|
Payload: string(rawManifest),
|
|
CreatedAt: timestamp,
|
|
UpdatedAt: timestamp,
|
|
}
|
|
// Make config descriptor
|
|
ociConfig := manifest.Config
|
|
configDescr := descr.Blob{
|
|
ID: auxuuid.NewUUID(),
|
|
Name: name,
|
|
Reference: reference,
|
|
MediaType: ociConfig.MediaType,
|
|
Digest: string(ociConfig.Digest),
|
|
Size: ociConfig.Size,
|
|
CreatedAt: timestamp,
|
|
UpdatedAt: timestamp,
|
|
}
|
|
blobDescrs = append(blobDescrs, configDescr)
|
|
// Make blob descriptions
|
|
layerMap := make(map[string]bool)
|
|
for _, layer := range manifest.Layers {
|
|
blobDescr := descr.Blob{
|
|
ID: auxuuid.NewUUID(),
|
|
Name: name,
|
|
Reference: reference,
|
|
MediaType: layer.MediaType,
|
|
Digest: string(layer.Digest),
|
|
Size: layer.Size,
|
|
CreatedAt: timestamp,
|
|
UpdatedAt: timestamp,
|
|
}
|
|
_, alreadyAdded := layerMap[string(layer.Digest)]
|
|
if !alreadyAdded {
|
|
blobDescrs = append(blobDescrs, blobDescr)
|
|
layerMap[string(layer.Digest)] = true
|
|
}
|
|
}
|
|
return mandescr, blobDescrs, err
|
|
}
|
|
|
|
func layersDiff(name, reference string, existingManifest, incomingManifest *ocispec.Manifest, rawManifest []byte) ([]descr.Blob, []descr.Blob, error) {
|
|
var err error
|
|
newBlobDescrs := make([]descr.Blob, 0)
|
|
delBlobDescrs := make([]descr.Blob, 0)
|
|
|
|
// Calculating old layers
|
|
delLayers := make([]ocispec.Descriptor, 0)
|
|
for _, oldLayer := range existingManifest.Layers {
|
|
uniq := true
|
|
for _, newLayer := range incomingManifest.Layers {
|
|
if oldLayer.Digest == newLayer.Digest {
|
|
uniq = false
|
|
}
|
|
}
|
|
if uniq {
|
|
delLayers = append(delLayers, oldLayer)
|
|
}
|
|
}
|
|
// Calculating new layers
|
|
newLayers := make([]ocispec.Descriptor, 0)
|
|
for _, newLayer := range incomingManifest.Layers {
|
|
uniq := true
|
|
for _, oldLayer := range existingManifest.Layers {
|
|
if oldLayer.Digest == newLayer.Digest {
|
|
uniq = false
|
|
}
|
|
}
|
|
if uniq {
|
|
newLayers = append(newLayers, newLayer)
|
|
}
|
|
}
|
|
if incomingManifest.Config.Digest != existingManifest.Config.Digest {
|
|
delLayers = append(delLayers, existingManifest.Config)
|
|
newLayers = append(newLayers, incomingManifest.Config)
|
|
}
|
|
// Converting to new blob
|
|
timestamp := auxtool.TimeNow()
|
|
for _, layer := range newLayers {
|
|
blobDescr := descr.Blob{
|
|
ID: auxuuid.NewUUID(),
|
|
Name: name,
|
|
Reference: reference,
|
|
MediaType: layer.MediaType,
|
|
Digest: string(layer.Digest),
|
|
Size: layer.Size,
|
|
CreatedAt: timestamp,
|
|
UpdatedAt: timestamp,
|
|
}
|
|
newBlobDescrs = append(newBlobDescrs, blobDescr)
|
|
}
|
|
// Converting to old blobs
|
|
for _, layer := range delLayers {
|
|
blobDescr := descr.Blob{
|
|
ID: auxuuid.NewUUID(),
|
|
Name: name,
|
|
Reference: reference,
|
|
MediaType: layer.MediaType,
|
|
Digest: string(layer.Digest),
|
|
Size: layer.Size,
|
|
}
|
|
delBlobDescrs = append(delBlobDescrs, blobDescr)
|
|
}
|
|
return newBlobDescrs, delBlobDescrs, err
|
|
}
|