0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00
zot/pkg/meta/convert/convert_proto.go
peusebiu 9074f8483b
feat(retention): added image retention policies (#1866)
feat(metaDB): add more image statistics info

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
2023-11-01 09:16:18 -07:00

395 lines
11 KiB
Go

package convert
import (
"time"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
"google.golang.org/protobuf/types/known/timestamppb"
"zotregistry.io/zot/pkg/common"
proto_go "zotregistry.io/zot/pkg/meta/proto/gen"
mTypes "zotregistry.io/zot/pkg/meta/types"
)
func GetProtoRepoMeta(repo mTypes.RepoMeta) *proto_go.RepoMeta {
return &proto_go.RepoMeta{
Name: repo.Name,
Tags: GetProtoTags(repo.Tags),
Statistics: GetProtoStatistics(repo.Statistics),
Signatures: GetProtoSignatures(repo.Signatures),
Referrers: GetProtoReferrers(repo.Referrers),
Size: int32(repo.Size),
Vendors: repo.Vendors,
Platforms: GetProtoPlatforms(repo.Platforms),
LastUpdatedImage: GetProtoLastUpdatedImage(repo.LastUpdatedImage),
}
}
func GetProtoImageMeta(imageMeta mTypes.ImageMeta) *proto_go.ImageMeta {
switch imageMeta.MediaType {
case ispec.MediaTypeImageManifest:
if len(imageMeta.Manifests) == 0 {
return nil
}
manifestData := imageMeta.Manifests[0]
return GetProtoImageManifestData(manifestData.Manifest, manifestData.Config, manifestData.Size,
manifestData.Digest.String())
case ispec.MediaTypeImageIndex:
if imageMeta.Index == nil {
return nil
}
return GetProtoImageIndexMeta(*imageMeta.Index, imageMeta.Size, imageMeta.Digest.String())
default:
return nil
}
}
func GetProtoImageManifestData(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string,
) *proto_go.ImageMeta {
return &proto_go.ImageMeta{
MediaType: ispec.MediaTypeImageManifest,
Manifests: []*proto_go.ManifestMeta{GetProtoManifestMeta(manifestContent, configContent, size, digest)},
Index: nil,
}
}
func GetProtoManifestMeta(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string,
) *proto_go.ManifestMeta {
return &proto_go.ManifestMeta{
Digest: digest,
Size: size,
Manifest: &proto_go.Manifest{
Versioned: &proto_go.Versioned{SchemaVersion: int32(manifestContent.SchemaVersion)},
Config: &proto_go.Descriptor{
Digest: manifestContent.Config.Digest.String(),
Size: manifestContent.Config.Size,
MediaType: manifestContent.Config.MediaType,
},
MediaType: ref(ispec.MediaTypeImageManifest),
ArtifactType: &manifestContent.ArtifactType,
Layers: getProtoManifestLayers(manifestContent.Layers),
Subject: getProtoDesc(manifestContent.Subject),
Annotations: manifestContent.Annotations,
},
Config: &proto_go.Image{
Created: GetProtoTime(configContent.Created),
Author: &configContent.Author,
Platform: GetProtoPlatform(&configContent.Platform),
Config: &proto_go.ImageConfig{
User: configContent.Config.User,
ExposedPorts: getProtoExposedPorts(configContent.Config.ExposedPorts),
Env: configContent.Config.Env,
Entrypoint: configContent.Config.Entrypoint,
Cmd: configContent.Config.Cmd,
Volumes: getProtoConfigVolumes(configContent.Config.Volumes),
WorkingDir: &configContent.Config.WorkingDir,
Labels: configContent.Config.Labels,
StopSignal: &configContent.Config.StopSignal,
},
RootFS: &proto_go.RootFS{
Type: configContent.RootFS.Type,
DiffIDs: getProtoDiffIDs(configContent.RootFS.DiffIDs),
},
History: getProtoHistory(configContent.History),
},
}
}
func GetProtoImageIndexMeta(indexContent ispec.Index, size int64, digest string) *proto_go.ImageMeta {
return &proto_go.ImageMeta{
MediaType: ispec.MediaTypeImageIndex,
Index: &proto_go.IndexMeta{
Size: size,
Digest: digest,
Index: &proto_go.Index{
Versioned: &proto_go.Versioned{SchemaVersion: int32(indexContent.Versioned.SchemaVersion)},
MediaType: ref(ispec.MediaTypeImageIndex),
ArtifactType: ref(common.GetIndexArtifactType(indexContent)),
Manifests: getProtoManifestList(indexContent.Manifests),
Subject: getProtoDesc(indexContent.Subject),
Annotations: indexContent.Annotations,
},
},
}
}
func GetProtoStatistics(stats map[string]mTypes.DescriptorStatistics) map[string]*proto_go.DescriptorStatistics {
results := map[string]*proto_go.DescriptorStatistics{}
for digest, stat := range stats {
results[digest] = &proto_go.DescriptorStatistics{
DownloadCount: int32(stat.DownloadCount),
LastPullTimestamp: timestamppb.New(stat.LastPullTimestamp),
PushTimestamp: timestamppb.New(stat.PushTimestamp),
PushedBy: stat.PushedBy,
}
}
return results
}
func GetProtoPlatforms(platforms []ispec.Platform) []*proto_go.Platform {
result := []*proto_go.Platform{}
for i := range platforms {
result = append(result, &proto_go.Platform{
OS: platforms[i].OS,
Architecture: platforms[i].Architecture,
})
}
return result
}
func GetProtoReferrers(refs map[string][]mTypes.ReferrerInfo) map[string]*proto_go.ReferrersInfo {
results := map[string]*proto_go.ReferrersInfo{}
for digest, ref := range refs {
referrersInfoList := []*proto_go.ReferrerInfo{}
for _, dbRef := range ref {
referrersInfoList = append(referrersInfoList, GetProtoReferrerInfo(dbRef))
}
results[digest] = &proto_go.ReferrersInfo{List: referrersInfoList}
}
return results
}
func GetProtoSignatures(sigs map[string]mTypes.ManifestSignatures) map[string]*proto_go.ManifestSignatures {
results := map[string]*proto_go.ManifestSignatures{}
for digest, dbSignatures := range sigs {
imageSignatures := &proto_go.ManifestSignatures{Map: map[string]*proto_go.SignaturesInfo{}}
for signatureName, signatureInfo := range dbSignatures {
imageSignatures.Map[signatureName] = &proto_go.SignaturesInfo{List: GetProtoSignaturesInfo(signatureInfo)}
}
results[digest] = imageSignatures
}
return results
}
func GetProtoSignaturesInfo(sigsInfo []mTypes.SignatureInfo) []*proto_go.SignatureInfo {
results := []*proto_go.SignatureInfo{}
for _, sigInfo := range sigsInfo {
results = append(results, &proto_go.SignatureInfo{
SignatureManifestDigest: sigInfo.SignatureManifestDigest,
LayersInfo: GetProtoLayersInfo(sigInfo.LayersInfo),
})
}
return results
}
func GetProtoLayersInfo(layersInfo []mTypes.LayerInfo) []*proto_go.LayersInfo {
result := make([]*proto_go.LayersInfo, 0, len(layersInfo))
for _, layerInfo := range layersInfo {
result = append(result, &proto_go.LayersInfo{
LayerDigest: layerInfo.LayerDigest,
LayerContent: layerInfo.LayerContent,
SignatureKey: layerInfo.SignatureKey,
Signer: layerInfo.Signer,
Date: timestamppb.New(layerInfo.Date),
})
}
return result
}
func getProtoManifestLayers(layers []ispec.Descriptor) []*proto_go.Descriptor {
protoLayers := []*proto_go.Descriptor{}
for _, layer := range layers {
layer := layer
protoLayers = append(protoLayers, getProtoDesc(&layer))
}
return protoLayers
}
func getProtoDesc(descriptor *ispec.Descriptor) *proto_go.Descriptor {
if descriptor == nil {
return nil
}
return &proto_go.Descriptor{
MediaType: descriptor.MediaType,
Digest: descriptor.Digest.String(),
Size: descriptor.Size,
URLs: descriptor.URLs,
Annotations: descriptor.Annotations,
Data: descriptor.Data,
Platform: GetProtoPlatform(descriptor.Platform),
ArtifactType: &descriptor.ArtifactType,
}
}
func getProtoManifestList(manifests []ispec.Descriptor) []*proto_go.Descriptor {
result := make([]*proto_go.Descriptor, 0, len(manifests))
for _, manifest := range manifests {
result = append(result, &proto_go.Descriptor{
MediaType: manifest.MediaType,
Digest: manifest.Digest.String(),
Size: manifest.Size,
URLs: manifest.URLs,
Annotations: manifest.Annotations,
Data: manifest.Data,
Platform: GetProtoPlatform(manifest.Platform),
ArtifactType: ref(manifest.ArtifactType),
})
}
return result
}
func GetProtoPlatform(platform *ispec.Platform) *proto_go.Platform {
if platform == nil {
return nil
}
return &proto_go.Platform{
Architecture: platform.Architecture,
OS: platform.OS,
OSVersion: ref(platform.OSVersion),
OSFeatures: platform.OSFeatures,
Variant: ref(platform.Variant),
}
}
func getProtoHistory(historySlice []ispec.History) []*proto_go.History {
protoHistory := []*proto_go.History{}
for _, history := range historySlice {
history := history
protoHistory = append(protoHistory, &proto_go.History{
Created: GetProtoTime(history.Created),
CreatedBy: &history.CreatedBy,
Author: &history.Author,
Comment: &history.Comment,
EmptyLayer: &history.EmptyLayer,
})
}
return protoHistory
}
func getProtoDiffIDs(digests []godigest.Digest) []string {
digestsStr := []string{}
for _, digest := range digests {
digestsStr = append(digestsStr, digest.String())
}
return digestsStr
}
func getProtoExposedPorts(exposedPorts map[string]struct{}) map[string]*proto_go.EmptyMessage {
protoPorts := map[string]*proto_go.EmptyMessage{}
for i := range exposedPorts {
protoPorts[i] = &proto_go.EmptyMessage{}
}
return protoPorts
}
func getProtoConfigVolumes(volumes map[string]struct{}) map[string]*proto_go.EmptyMessage {
protoVolumes := map[string]*proto_go.EmptyMessage{}
for i := range volumes {
protoVolumes[i] = &proto_go.EmptyMessage{}
}
return protoVolumes
}
func GetProtoReferrerInfo(referrer mTypes.ReferrerInfo) *proto_go.ReferrerInfo {
return &proto_go.ReferrerInfo{
Digest: referrer.Digest,
MediaType: referrer.MediaType,
ArtifactType: referrer.ArtifactType,
Size: int64(referrer.Size),
Annotations: referrer.Annotations,
}
}
func GetProtoTime(time *time.Time) *timestamppb.Timestamp {
if time == nil {
return nil
}
return timestamppb.New(*time)
}
func GetProtoTags(tags map[string]mTypes.Descriptor) map[string]*proto_go.TagDescriptor {
resultMap := map[string]*proto_go.TagDescriptor{}
for tag, tagDescriptor := range tags {
resultMap[tag] = &proto_go.TagDescriptor{
Digest: tagDescriptor.Digest,
MediaType: tagDescriptor.MediaType,
}
}
return resultMap
}
func GetProtoLastUpdatedImage(lastUpdatedImage *mTypes.LastUpdatedImage) *proto_go.RepoLastUpdatedImage {
if lastUpdatedImage == nil {
return nil
}
return &proto_go.RepoLastUpdatedImage{
LastUpdated: GetProtoTime(lastUpdatedImage.LastUpdated),
MediaType: lastUpdatedImage.MediaType,
Digest: lastUpdatedImage.Digest,
Tag: lastUpdatedImage.Tag,
}
}
func GetProtoEarlierUpdatedImage(repoLastImage *proto_go.RepoLastUpdatedImage, lastImage *proto_go.RepoLastUpdatedImage,
) *proto_go.RepoLastUpdatedImage {
if repoLastImage == nil {
return lastImage
}
if lastImage == nil || lastImage.LastUpdated == nil {
return repoLastImage
}
if repoLastImage.LastUpdated == nil {
return lastImage
}
if repoLastImage.LastUpdated.AsTime().Before(lastImage.LastUpdated.AsTime()) {
return lastImage
}
return repoLastImage
}
func ref[T any](input T) *T {
ref := input
return &ref
}
func deref[T any](pointer *T, defaultVal T) T {
if pointer != nil {
return *pointer
}
return defaultVal
}