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.go
Andrei Aaron 7d87558b7e
fix: various lint issues (#2571)
Originally found by @jkroepke in: https://github.com/project-zot/zot/actions/runs/10056774230/job/27796324933?pr=2556
And https://github.com/project-zot/zot/pull/2556 in general

This commit covers:
- (canonicalheader) capitalization of Docker-Content-Digest header
- (protogetter) the proto getters were not used, they check for nil pointers, we should switch to using them
- (zerologlint) fix the false positive

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
2024-07-25 10:14:22 -07:00

630 lines
18 KiB
Go

package convert
import (
"time"
godigest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
"google.golang.org/protobuf/types/known/timestamppb"
"zotregistry.dev/zot/pkg/common"
proto_go "zotregistry.dev/zot/pkg/meta/proto/gen"
mTypes "zotregistry.dev/zot/pkg/meta/types"
)
func GetHistory(history []*proto_go.History) []ispec.History {
if history == nil {
return nil
}
results := make([]ispec.History, 0, len(history))
for _, his := range history {
results = append(results, ispec.History{
Created: ref(his.GetCreated().AsTime()),
CreatedBy: his.GetCreatedBy(),
Author: his.GetAuthor(),
Comment: his.GetComment(),
EmptyLayer: his.GetEmptyLayer(),
})
}
return results
}
func GetImageArtifactType(imageMeta *proto_go.ImageMeta) string {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
manifestArtifactType := imageMeta.GetManifests()[0].GetManifest().GetArtifactType()
if manifestArtifactType != "" {
return manifestArtifactType
}
return imageMeta.GetManifests()[0].GetManifest().GetConfig().GetMediaType()
case ispec.MediaTypeImageIndex:
return imageMeta.GetIndex().GetIndex().GetArtifactType()
default:
return ""
}
}
func GetImageManifestSize(imageMeta *proto_go.ImageMeta) int64 {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
return imageMeta.GetManifests()[0].GetSize()
case ispec.MediaTypeImageIndex:
return imageMeta.GetIndex().GetSize()
default:
return 0
}
}
func GetImageDigest(imageMeta *proto_go.ImageMeta) godigest.Digest {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
return godigest.Digest(imageMeta.GetManifests()[0].GetDigest())
case ispec.MediaTypeImageIndex:
return godigest.Digest(imageMeta.GetIndex().GetDigest())
default:
return ""
}
}
func GetImageDigestStr(imageMeta *proto_go.ImageMeta) string {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
return imageMeta.GetManifests()[0].GetDigest()
case ispec.MediaTypeImageIndex:
return imageMeta.GetIndex().GetDigest()
default:
return ""
}
}
func GetImageAnnotations(imageMeta *proto_go.ImageMeta) map[string]string {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
return imageMeta.GetManifests()[0].GetManifest().GetAnnotations()
case ispec.MediaTypeImageIndex:
return imageMeta.GetIndex().GetIndex().GetAnnotations()
default:
return map[string]string{}
}
}
func GetImageSubject(imageMeta *proto_go.ImageMeta) *ispec.Descriptor {
switch imageMeta.GetMediaType() {
case ispec.MediaTypeImageManifest:
if imageMeta.GetManifests()[0].GetManifest().GetSubject() == nil {
return nil
}
return GetDescriptorRef(imageMeta.GetManifests()[0].GetManifest().GetSubject())
case ispec.MediaTypeImageIndex:
return GetDescriptorRef(imageMeta.GetIndex().GetIndex().GetSubject())
default:
return nil
}
}
func GetDescriptorRef(descriptor *proto_go.Descriptor) *ispec.Descriptor {
if descriptor == nil {
return nil
}
platform := GetPlatformRef(descriptor.GetPlatform())
return &ispec.Descriptor{
MediaType: descriptor.GetMediaType(),
Digest: godigest.Digest(descriptor.GetDigest()),
Size: descriptor.GetSize(),
URLs: descriptor.GetURLs(),
Data: descriptor.GetData(),
Platform: platform,
ArtifactType: descriptor.GetArtifactType(),
Annotations: descriptor.GetAnnotations(),
}
}
func GetPlatform(platform *proto_go.Platform) ispec.Platform {
if platform == nil {
return ispec.Platform{}
}
return ispec.Platform{
Architecture: platform.GetArchitecture(),
OS: platform.GetOS(),
OSVersion: platform.GetOSVersion(),
OSFeatures: platform.GetOSFeatures(),
Variant: platform.GetVariant(),
}
}
func GetPlatformRef(platform *proto_go.Platform) *ispec.Platform {
if platform == nil {
return nil
}
return &ispec.Platform{
Architecture: platform.GetArchitecture(),
OS: platform.GetOS(),
OSVersion: platform.GetOSVersion(),
OSFeatures: platform.GetOSFeatures(),
Variant: platform.GetVariant(),
}
}
func GetLayers(descriptors []*proto_go.Descriptor) []ispec.Descriptor {
results := make([]ispec.Descriptor, 0, len(descriptors))
for _, desc := range descriptors {
results = append(results, ispec.Descriptor{
MediaType: desc.GetMediaType(),
Digest: godigest.Digest(desc.GetDigest()),
Size: desc.GetSize(),
})
}
return results
}
func GetSubject(subj *proto_go.Descriptor) *ispec.Descriptor {
if subj == nil {
return nil
}
return &ispec.Descriptor{
MediaType: subj.GetMediaType(),
Digest: godigest.Digest(subj.GetDigest()),
Size: subj.GetSize(),
}
}
func GetReferrers(refs map[string]*proto_go.ReferrersInfo) map[string][]mTypes.ReferrerInfo {
results := map[string][]mTypes.ReferrerInfo{}
for digest, ref := range refs {
referrers := []mTypes.ReferrerInfo{}
for _, dbRef := range ref.GetList() {
referrers = append(referrers, mTypes.ReferrerInfo{
Digest: dbRef.GetDigest(),
MediaType: dbRef.GetMediaType(),
ArtifactType: dbRef.GetArtifactType(),
Size: int(dbRef.GetSize()), // int64 to int32, need to review this later
Annotations: dbRef.GetAnnotations(),
})
}
results[digest] = referrers
}
return results
}
func GetImageReferrers(refs *proto_go.ReferrersInfo) []mTypes.ReferrerInfo {
if refs == nil {
return []mTypes.ReferrerInfo{}
}
results := []mTypes.ReferrerInfo{}
for _, dbRef := range refs.GetList() {
results = append(results, mTypes.ReferrerInfo{
Digest: dbRef.GetDigest(),
MediaType: dbRef.GetMediaType(),
ArtifactType: dbRef.GetArtifactType(),
Size: int(dbRef.GetSize()), // int64 to int32, need to review this later
Annotations: dbRef.GetAnnotations(),
})
}
return results
}
func GetSignatures(sigs map[string]*proto_go.ManifestSignatures) map[string]mTypes.ManifestSignatures {
results := map[string]mTypes.ManifestSignatures{}
for digest, dbSignatures := range sigs {
imageSignatures := mTypes.ManifestSignatures{}
for signatureName, signatureInfo := range dbSignatures.GetMap() {
imageSignatures[signatureName] = GetSignaturesInfo(signatureInfo.GetList())
}
results[digest] = imageSignatures
}
return results
}
func GetImageSignatures(sigs *proto_go.ManifestSignatures) mTypes.ManifestSignatures {
if sigs == nil {
return mTypes.ManifestSignatures{}
}
results := mTypes.ManifestSignatures{}
for signatureName, signatureInfo := range sigs.GetMap() {
results[signatureName] = GetSignaturesInfo(signatureInfo.GetList())
}
return results
}
func GetSignaturesInfo(sigsInfo []*proto_go.SignatureInfo) []mTypes.SignatureInfo {
results := []mTypes.SignatureInfo{}
for _, siginfo := range sigsInfo {
results = append(results, mTypes.SignatureInfo{
SignatureManifestDigest: siginfo.GetSignatureManifestDigest(),
LayersInfo: GetLayersInfo(siginfo.GetLayersInfo()),
})
}
return results
}
func GetLayersInfo(layersInfo []*proto_go.LayersInfo) []mTypes.LayerInfo {
results := []mTypes.LayerInfo{}
for _, layerInfo := range layersInfo {
date := time.Time{}
if layerInfo.GetDate() != nil {
date = layerInfo.GetDate().AsTime()
}
results = append(results, mTypes.LayerInfo{
LayerDigest: layerInfo.GetLayerDigest(),
LayerContent: layerInfo.GetLayerContent(),
SignatureKey: layerInfo.GetSignatureKey(),
Signer: layerInfo.GetSigner(),
Date: date,
})
}
return results
}
func GetStatisticsMap(stats map[mTypes.ImageDigest]*proto_go.DescriptorStatistics,
) map[mTypes.ImageDigest]mTypes.DescriptorStatistics {
results := map[mTypes.ImageDigest]mTypes.DescriptorStatistics{}
for digest, stat := range stats {
results[digest] = mTypes.DescriptorStatistics{
DownloadCount: int(stat.GetDownloadCount()),
LastPullTimestamp: stat.GetLastPullTimestamp().AsTime(),
PushTimestamp: stat.GetPushTimestamp().AsTime(),
PushedBy: stat.GetPushedBy(),
}
}
return results
}
func GetImageStatistics(stats *proto_go.DescriptorStatistics) mTypes.DescriptorStatistics {
if stats == nil {
return mTypes.DescriptorStatistics{}
}
return mTypes.DescriptorStatistics{
DownloadCount: int(stats.GetDownloadCount()),
LastPullTimestamp: stats.GetLastPullTimestamp().AsTime(),
PushTimestamp: stats.GetPushTimestamp().AsTime(),
PushedBy: stats.GetPushedBy(),
}
}
func GetImageManifestMeta(manifestContent ispec.Manifest, configContent ispec.Image, size int64,
digest godigest.Digest,
) mTypes.ImageMeta {
return mTypes.ImageMeta{
MediaType: ispec.MediaTypeImageManifest,
Digest: digest,
Size: size,
Manifests: []mTypes.ManifestMeta{
{
Digest: digest,
Size: size,
Config: configContent,
Manifest: manifestContent,
},
},
}
}
func GetImageIndexMeta(indexContent ispec.Index, size int64, digest godigest.Digest) mTypes.ImageMeta {
return mTypes.ImageMeta{
MediaType: ispec.MediaTypeImageIndex,
Index: &indexContent,
Manifests: GetManifests(indexContent.Manifests),
Size: size,
Digest: digest,
}
}
func GetTags(tags map[mTypes.Tag]*proto_go.TagDescriptor) map[mTypes.Tag]mTypes.Descriptor {
resultMap := map[mTypes.Tag]mTypes.Descriptor{}
for tag, tagDescriptor := range tags {
resultMap[tag] = mTypes.Descriptor{
Digest: tagDescriptor.GetDigest(),
MediaType: tagDescriptor.GetMediaType(),
}
}
return resultMap
}
func GetManifests(descriptors []ispec.Descriptor) []mTypes.ManifestMeta {
manifestList := []mTypes.ManifestMeta{}
for _, manifest := range descriptors {
manifestList = append(manifestList, mTypes.ManifestMeta{
Digest: manifest.Digest,
Size: manifest.Size,
})
}
return manifestList
}
func GetTime(time *timestamppb.Timestamp) *time.Time {
if time == nil {
return nil
}
return ref(time.AsTime())
}
func GetFullImageMetaFromProto(tag string, protoRepoMeta *proto_go.RepoMeta, protoImageMeta *proto_go.ImageMeta,
) mTypes.FullImageMeta {
if protoRepoMeta == nil {
return mTypes.FullImageMeta{}
}
imageMeta := GetImageMeta(protoImageMeta)
imageDigest := imageMeta.Digest.String()
return mTypes.FullImageMeta{
Repo: protoRepoMeta.GetName(),
Tag: tag,
MediaType: imageMeta.MediaType,
Digest: imageMeta.Digest,
Size: imageMeta.Size,
Index: imageMeta.Index,
Manifests: GetFullManifestData(protoRepoMeta, imageMeta.Manifests),
IsStarred: protoRepoMeta.GetIsStarred(),
IsBookmarked: protoRepoMeta.GetIsBookmarked(),
Referrers: GetImageReferrers(protoRepoMeta.GetReferrers()[imageDigest]),
Statistics: GetImageStatistics(protoRepoMeta.GetStatistics()[imageDigest]),
Signatures: GetImageSignatures(protoRepoMeta.GetSignatures()[imageDigest]),
}
}
func GetFullManifestData(protoRepoMeta *proto_go.RepoMeta, manifestData []mTypes.ManifestMeta,
) []mTypes.FullManifestMeta {
if protoRepoMeta == nil {
return []mTypes.FullManifestMeta{}
}
results := []mTypes.FullManifestMeta{}
for i := range manifestData {
results = append(results, mTypes.FullManifestMeta{
ManifestMeta: manifestData[i],
Referrers: GetImageReferrers(protoRepoMeta.GetReferrers()[manifestData[i].Digest.String()]),
Statistics: GetImageStatistics(protoRepoMeta.GetStatistics()[manifestData[i].Digest.String()]),
Signatures: GetImageSignatures(protoRepoMeta.GetSignatures()[manifestData[i].Digest.String()]),
})
}
return results
}
func GetRepoMeta(protoRepoMeta *proto_go.RepoMeta) mTypes.RepoMeta {
if protoRepoMeta == nil {
return mTypes.RepoMeta{}
}
repoDownloads := int32(0)
for _, descriptor := range protoRepoMeta.GetTags() {
if statistic := protoRepoMeta.GetStatistics()[descriptor.GetDigest()]; statistic != nil {
repoDownloads += statistic.GetDownloadCount()
}
}
return mTypes.RepoMeta{
Name: protoRepoMeta.GetName(),
Tags: GetTags(protoRepoMeta.GetTags()),
Rank: int(protoRepoMeta.GetRank()),
Size: protoRepoMeta.GetSize(),
Platforms: GetPlatforms(protoRepoMeta.GetPlatforms()),
Vendors: protoRepoMeta.GetVendors(),
IsStarred: protoRepoMeta.GetIsStarred(),
IsBookmarked: protoRepoMeta.GetIsBookmarked(),
StarCount: int(protoRepoMeta.GetStars()),
DownloadCount: int(repoDownloads),
LastUpdatedImage: GetLastUpdatedImage(protoRepoMeta.GetLastUpdatedImage()),
Statistics: GetStatisticsMap(protoRepoMeta.GetStatistics()),
Signatures: GetSignatures(protoRepoMeta.GetSignatures()),
Referrers: GetReferrers(protoRepoMeta.GetReferrers()),
}
}
func GetPlatforms(platforms []*proto_go.Platform) []ispec.Platform {
result := []ispec.Platform{}
for i := range platforms {
result = append(result, GetPlatform(platforms[i]))
}
return result
}
func AddProtoPlatforms(platforms []*proto_go.Platform, newPlatforms []*proto_go.Platform) []*proto_go.Platform {
for _, newPlatform := range newPlatforms {
if !ContainsProtoPlatform(platforms, newPlatform) {
platforms = append(platforms, newPlatform)
}
}
return platforms
}
func ContainsProtoPlatform(platforms []*proto_go.Platform, platform *proto_go.Platform) bool {
for i := range platforms {
if platforms[i].GetOS() == platform.GetOS() && platforms[i].GetArchitecture() == platform.GetArchitecture() {
return true
}
}
return false
}
func AddVendors(vendors []string, newVendors []string) []string {
for _, newVendor := range newVendors {
if !common.Contains(vendors, newVendor) {
vendors = append(vendors, newVendor)
}
}
return vendors
}
func GetLastUpdatedImage(protoLastUpdated *proto_go.RepoLastUpdatedImage) *mTypes.LastUpdatedImage {
if protoLastUpdated == nil {
return nil
}
return &mTypes.LastUpdatedImage{
Descriptor: mTypes.Descriptor{
Digest: protoLastUpdated.GetDigest(),
MediaType: protoLastUpdated.GetMediaType(),
},
Tag: protoLastUpdated.GetTag(),
LastUpdated: GetTime(protoLastUpdated.GetLastUpdated()),
}
}
func GetImageMeta(dbImageMeta *proto_go.ImageMeta) mTypes.ImageMeta {
if dbImageMeta == nil {
return mTypes.ImageMeta{}
}
imageMeta := mTypes.ImageMeta{
MediaType: dbImageMeta.GetMediaType(),
Size: GetImageManifestSize(dbImageMeta),
Digest: GetImageDigest(dbImageMeta),
}
if dbImageMeta.GetMediaType() == ispec.MediaTypeImageIndex {
manifests := make([]ispec.Descriptor, 0, len(dbImageMeta.GetManifests()))
for _, manifest := range dbImageMeta.GetIndex().GetIndex().GetManifests() {
manifests = append(manifests, ispec.Descriptor{
MediaType: manifest.GetMediaType(),
Digest: godigest.Digest(manifest.GetDigest()),
Size: manifest.GetSize(),
})
}
imageMeta.Index = &ispec.Index{
Versioned: specs.Versioned{SchemaVersion: int(dbImageMeta.GetIndex().GetIndex().Versioned.GetSchemaVersion())},
MediaType: ispec.MediaTypeImageIndex,
Manifests: manifests,
Subject: GetImageSubject(dbImageMeta),
ArtifactType: GetImageArtifactType(dbImageMeta),
Annotations: GetImageAnnotations(dbImageMeta),
}
}
manifestDataList := make([]mTypes.ManifestMeta, 0, len(dbImageMeta.GetManifests()))
for _, manifest := range dbImageMeta.GetManifests() {
manifestDataList = append(manifestDataList, mTypes.ManifestMeta{
Size: manifest.GetSize(),
Digest: godigest.Digest(manifest.GetDigest()),
Manifest: ispec.Manifest{
Versioned: specs.Versioned{SchemaVersion: int(manifest.GetManifest().GetVersioned().GetSchemaVersion())},
MediaType: manifest.GetManifest().GetMediaType(),
ArtifactType: manifest.GetManifest().GetArtifactType(),
Config: ispec.Descriptor{
MediaType: manifest.GetManifest().GetConfig().GetMediaType(),
Size: manifest.GetManifest().GetConfig().GetSize(),
Digest: godigest.Digest(manifest.GetManifest().GetConfig().GetDigest()),
},
Layers: GetLayers(manifest.GetManifest().GetLayers()),
Subject: GetSubject(manifest.GetManifest().GetSubject()),
Annotations: manifest.GetManifest().GetAnnotations(),
},
Config: ispec.Image{
Created: GetTime(manifest.GetConfig().GetCreated()),
Author: manifest.GetConfig().GetAuthor(),
Platform: GetPlatform(manifest.GetConfig().GetPlatform()),
Config: ispec.ImageConfig{
User: manifest.GetConfig().GetConfig().GetUser(),
ExposedPorts: GetExposedPorts(manifest.GetConfig().GetConfig().GetExposedPorts()),
Env: manifest.GetConfig().GetConfig().GetEnv(),
Entrypoint: manifest.GetConfig().GetConfig().GetEntrypoint(),
Cmd: manifest.GetConfig().GetConfig().GetCmd(),
Volumes: GetConfigVolumes(manifest.GetConfig().GetConfig().GetVolumes()),
WorkingDir: manifest.GetConfig().GetConfig().GetWorkingDir(),
Labels: manifest.GetConfig().GetConfig().GetLabels(),
StopSignal: manifest.GetConfig().GetConfig().GetStopSignal(),
},
RootFS: ispec.RootFS{
Type: manifest.GetConfig().GetRootFS().GetType(),
DiffIDs: GetDiffIDs(manifest.GetConfig().GetRootFS().GetDiffIDs()),
},
History: GetHistory(manifest.GetConfig().GetHistory()),
},
})
}
imageMeta.Manifests = manifestDataList
return imageMeta
}
func GetExposedPorts(exposedPorts map[string]*proto_go.EmptyMessage) map[string]struct{} {
if exposedPorts == nil {
return nil
}
result := map[string]struct{}{}
for key := range exposedPorts {
result[key] = struct{}{}
}
return result
}
func GetConfigVolumes(configVolumes map[string]*proto_go.EmptyMessage) map[string]struct{} {
if configVolumes == nil {
return nil
}
result := map[string]struct{}{}
for key := range configVolumes {
result[key] = struct{}{}
}
return result
}
func GetDiffIDs(diffIDs []string) []godigest.Digest {
result := make([]godigest.Digest, 0, len(diffIDs))
for i := range diffIDs {
result = append(result, godigest.Digest(diffIDs[i]))
}
return result
}