zotregistry.io/zot@v1.4.4-0.20231124084042-02a8ed785457/pkg/meta/convert/convert_proto.go (about) 1 package convert 2 3 import ( 4 "time" 5 6 godigest "github.com/opencontainers/go-digest" 7 ispec "github.com/opencontainers/image-spec/specs-go/v1" 8 "google.golang.org/protobuf/types/known/timestamppb" 9 10 "zotregistry.io/zot/pkg/common" 11 proto_go "zotregistry.io/zot/pkg/meta/proto/gen" 12 mTypes "zotregistry.io/zot/pkg/meta/types" 13 ) 14 15 func GetProtoRepoMeta(repo mTypes.RepoMeta) *proto_go.RepoMeta { 16 return &proto_go.RepoMeta{ 17 Name: repo.Name, 18 Tags: GetProtoTags(repo.Tags), 19 Statistics: GetProtoStatistics(repo.Statistics), 20 Signatures: GetProtoSignatures(repo.Signatures), 21 Referrers: GetProtoReferrers(repo.Referrers), 22 Size: int32(repo.Size), 23 Vendors: repo.Vendors, 24 Platforms: GetProtoPlatforms(repo.Platforms), 25 LastUpdatedImage: GetProtoLastUpdatedImage(repo.LastUpdatedImage), 26 Stars: int32(repo.StarCount), 27 Downloads: int32(repo.DownloadCount), 28 } 29 } 30 31 func GetProtoImageMeta(imageMeta mTypes.ImageMeta) *proto_go.ImageMeta { 32 switch imageMeta.MediaType { 33 case ispec.MediaTypeImageManifest: 34 if len(imageMeta.Manifests) == 0 { 35 return nil 36 } 37 manifestData := imageMeta.Manifests[0] 38 39 return GetProtoImageManifestData(manifestData.Manifest, manifestData.Config, manifestData.Size, 40 manifestData.Digest.String()) 41 case ispec.MediaTypeImageIndex: 42 if imageMeta.Index == nil { 43 return nil 44 } 45 46 return GetProtoImageIndexMeta(*imageMeta.Index, imageMeta.Size, imageMeta.Digest.String()) 47 default: 48 return nil 49 } 50 } 51 52 func GetProtoImageManifestData(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string, 53 ) *proto_go.ImageMeta { 54 return &proto_go.ImageMeta{ 55 MediaType: ispec.MediaTypeImageManifest, 56 Manifests: []*proto_go.ManifestMeta{GetProtoManifestMeta(manifestContent, configContent, size, digest)}, 57 Index: nil, 58 } 59 } 60 61 func GetProtoManifestMeta(manifestContent ispec.Manifest, configContent ispec.Image, size int64, digest string, 62 ) *proto_go.ManifestMeta { 63 return &proto_go.ManifestMeta{ 64 Digest: digest, 65 Size: size, 66 Manifest: &proto_go.Manifest{ 67 Versioned: &proto_go.Versioned{SchemaVersion: int32(manifestContent.SchemaVersion)}, 68 Config: &proto_go.Descriptor{ 69 Digest: manifestContent.Config.Digest.String(), 70 Size: manifestContent.Config.Size, 71 MediaType: manifestContent.Config.MediaType, 72 }, 73 MediaType: ref(ispec.MediaTypeImageManifest), 74 ArtifactType: &manifestContent.ArtifactType, 75 Layers: getProtoManifestLayers(manifestContent.Layers), 76 Subject: getProtoDesc(manifestContent.Subject), 77 Annotations: manifestContent.Annotations, 78 }, 79 Config: &proto_go.Image{ 80 Created: GetProtoTime(configContent.Created), 81 Author: &configContent.Author, 82 Platform: GetProtoPlatform(&configContent.Platform), 83 Config: &proto_go.ImageConfig{ 84 User: configContent.Config.User, 85 ExposedPorts: getProtoExposedPorts(configContent.Config.ExposedPorts), 86 Env: configContent.Config.Env, 87 Entrypoint: configContent.Config.Entrypoint, 88 Cmd: configContent.Config.Cmd, 89 Volumes: getProtoConfigVolumes(configContent.Config.Volumes), 90 WorkingDir: &configContent.Config.WorkingDir, 91 Labels: configContent.Config.Labels, 92 StopSignal: &configContent.Config.StopSignal, 93 }, 94 RootFS: &proto_go.RootFS{ 95 Type: configContent.RootFS.Type, 96 DiffIDs: getProtoDiffIDs(configContent.RootFS.DiffIDs), 97 }, 98 History: getProtoHistory(configContent.History), 99 }, 100 } 101 } 102 103 func GetProtoImageIndexMeta(indexContent ispec.Index, size int64, digest string) *proto_go.ImageMeta { 104 return &proto_go.ImageMeta{ 105 MediaType: ispec.MediaTypeImageIndex, 106 Index: &proto_go.IndexMeta{ 107 Size: size, 108 Digest: digest, 109 Index: &proto_go.Index{ 110 Versioned: &proto_go.Versioned{SchemaVersion: int32(indexContent.Versioned.SchemaVersion)}, 111 MediaType: ref(ispec.MediaTypeImageIndex), 112 ArtifactType: ref(common.GetIndexArtifactType(indexContent)), 113 Manifests: getProtoManifestList(indexContent.Manifests), 114 Subject: getProtoDesc(indexContent.Subject), 115 Annotations: indexContent.Annotations, 116 }, 117 }, 118 } 119 } 120 121 func GetProtoStatistics(stats map[string]mTypes.DescriptorStatistics) map[string]*proto_go.DescriptorStatistics { 122 results := map[string]*proto_go.DescriptorStatistics{} 123 124 for digest, stat := range stats { 125 results[digest] = &proto_go.DescriptorStatistics{ 126 DownloadCount: int32(stat.DownloadCount), 127 LastPullTimestamp: timestamppb.New(stat.LastPullTimestamp), 128 PushTimestamp: timestamppb.New(stat.PushTimestamp), 129 PushedBy: stat.PushedBy, 130 } 131 } 132 133 return results 134 } 135 136 func GetProtoPlatforms(platforms []ispec.Platform) []*proto_go.Platform { 137 result := []*proto_go.Platform{} 138 139 for i := range platforms { 140 result = append(result, &proto_go.Platform{ 141 OS: platforms[i].OS, 142 Architecture: platforms[i].Architecture, 143 }) 144 } 145 146 return result 147 } 148 149 func GetProtoReferrers(refs map[string][]mTypes.ReferrerInfo) map[string]*proto_go.ReferrersInfo { 150 results := map[string]*proto_go.ReferrersInfo{} 151 152 for digest, ref := range refs { 153 referrersInfoList := []*proto_go.ReferrerInfo{} 154 155 for _, dbRef := range ref { 156 referrersInfoList = append(referrersInfoList, GetProtoReferrerInfo(dbRef)) 157 } 158 159 results[digest] = &proto_go.ReferrersInfo{List: referrersInfoList} 160 } 161 162 return results 163 } 164 165 func GetProtoSignatures(sigs map[string]mTypes.ManifestSignatures) map[string]*proto_go.ManifestSignatures { 166 results := map[string]*proto_go.ManifestSignatures{} 167 168 for digest, dbSignatures := range sigs { 169 imageSignatures := &proto_go.ManifestSignatures{Map: map[string]*proto_go.SignaturesInfo{}} 170 171 for signatureName, signatureInfo := range dbSignatures { 172 imageSignatures.Map[signatureName] = &proto_go.SignaturesInfo{List: GetProtoSignaturesInfo(signatureInfo)} 173 } 174 175 results[digest] = imageSignatures 176 } 177 178 return results 179 } 180 181 func GetProtoSignaturesInfo(sigsInfo []mTypes.SignatureInfo) []*proto_go.SignatureInfo { 182 results := []*proto_go.SignatureInfo{} 183 184 for _, sigInfo := range sigsInfo { 185 results = append(results, &proto_go.SignatureInfo{ 186 SignatureManifestDigest: sigInfo.SignatureManifestDigest, 187 LayersInfo: GetProtoLayersInfo(sigInfo.LayersInfo), 188 }) 189 } 190 191 return results 192 } 193 194 func GetProtoLayersInfo(layersInfo []mTypes.LayerInfo) []*proto_go.LayersInfo { 195 result := make([]*proto_go.LayersInfo, 0, len(layersInfo)) 196 197 for _, layerInfo := range layersInfo { 198 result = append(result, &proto_go.LayersInfo{ 199 LayerDigest: layerInfo.LayerDigest, 200 LayerContent: layerInfo.LayerContent, 201 SignatureKey: layerInfo.SignatureKey, 202 Signer: layerInfo.Signer, 203 Date: timestamppb.New(layerInfo.Date), 204 }) 205 } 206 207 return result 208 } 209 210 func getProtoManifestLayers(layers []ispec.Descriptor) []*proto_go.Descriptor { 211 protoLayers := []*proto_go.Descriptor{} 212 213 for _, layer := range layers { 214 layer := layer 215 216 protoLayers = append(protoLayers, getProtoDesc(&layer)) 217 } 218 219 return protoLayers 220 } 221 222 func getProtoDesc(descriptor *ispec.Descriptor) *proto_go.Descriptor { 223 if descriptor == nil { 224 return nil 225 } 226 227 return &proto_go.Descriptor{ 228 MediaType: descriptor.MediaType, 229 Digest: descriptor.Digest.String(), 230 Size: descriptor.Size, 231 URLs: descriptor.URLs, 232 Annotations: descriptor.Annotations, 233 Data: descriptor.Data, 234 Platform: GetProtoPlatform(descriptor.Platform), 235 ArtifactType: &descriptor.ArtifactType, 236 } 237 } 238 239 func getProtoManifestList(manifests []ispec.Descriptor) []*proto_go.Descriptor { 240 result := make([]*proto_go.Descriptor, 0, len(manifests)) 241 242 for _, manifest := range manifests { 243 result = append(result, &proto_go.Descriptor{ 244 MediaType: manifest.MediaType, 245 Digest: manifest.Digest.String(), 246 Size: manifest.Size, 247 URLs: manifest.URLs, 248 Annotations: manifest.Annotations, 249 Data: manifest.Data, 250 Platform: GetProtoPlatform(manifest.Platform), 251 ArtifactType: ref(manifest.ArtifactType), 252 }) 253 } 254 255 return result 256 } 257 258 func GetProtoPlatform(platform *ispec.Platform) *proto_go.Platform { 259 if platform == nil { 260 return nil 261 } 262 263 return &proto_go.Platform{ 264 Architecture: platform.Architecture, 265 OS: platform.OS, 266 OSVersion: ref(platform.OSVersion), 267 OSFeatures: platform.OSFeatures, 268 Variant: ref(platform.Variant), 269 } 270 } 271 272 func getProtoHistory(historySlice []ispec.History) []*proto_go.History { 273 protoHistory := []*proto_go.History{} 274 275 for _, history := range historySlice { 276 history := history 277 278 protoHistory = append(protoHistory, &proto_go.History{ 279 Created: GetProtoTime(history.Created), 280 CreatedBy: &history.CreatedBy, 281 Author: &history.Author, 282 Comment: &history.Comment, 283 EmptyLayer: &history.EmptyLayer, 284 }) 285 } 286 287 return protoHistory 288 } 289 290 func getProtoDiffIDs(digests []godigest.Digest) []string { 291 digestsStr := []string{} 292 293 for _, digest := range digests { 294 digestsStr = append(digestsStr, digest.String()) 295 } 296 297 return digestsStr 298 } 299 300 func getProtoExposedPorts(exposedPorts map[string]struct{}) map[string]*proto_go.EmptyMessage { 301 protoPorts := map[string]*proto_go.EmptyMessage{} 302 303 for i := range exposedPorts { 304 protoPorts[i] = &proto_go.EmptyMessage{} 305 } 306 307 return protoPorts 308 } 309 310 func getProtoConfigVolumes(volumes map[string]struct{}) map[string]*proto_go.EmptyMessage { 311 protoVolumes := map[string]*proto_go.EmptyMessage{} 312 313 for i := range volumes { 314 protoVolumes[i] = &proto_go.EmptyMessage{} 315 } 316 317 return protoVolumes 318 } 319 320 func GetProtoReferrerInfo(referrer mTypes.ReferrerInfo) *proto_go.ReferrerInfo { 321 return &proto_go.ReferrerInfo{ 322 Digest: referrer.Digest, 323 MediaType: referrer.MediaType, 324 ArtifactType: referrer.ArtifactType, 325 Size: int64(referrer.Size), 326 Annotations: referrer.Annotations, 327 } 328 } 329 330 func GetProtoTime(time *time.Time) *timestamppb.Timestamp { 331 if time == nil { 332 return nil 333 } 334 335 return timestamppb.New(*time) 336 } 337 338 func GetProtoTags(tags map[string]mTypes.Descriptor) map[string]*proto_go.TagDescriptor { 339 resultMap := map[string]*proto_go.TagDescriptor{} 340 341 for tag, tagDescriptor := range tags { 342 resultMap[tag] = &proto_go.TagDescriptor{ 343 Digest: tagDescriptor.Digest, 344 MediaType: tagDescriptor.MediaType, 345 } 346 } 347 348 return resultMap 349 } 350 351 func GetProtoLastUpdatedImage(lastUpdatedImage *mTypes.LastUpdatedImage) *proto_go.RepoLastUpdatedImage { 352 if lastUpdatedImage == nil { 353 return nil 354 } 355 356 return &proto_go.RepoLastUpdatedImage{ 357 LastUpdated: GetProtoTime(lastUpdatedImage.LastUpdated), 358 MediaType: lastUpdatedImage.MediaType, 359 Digest: lastUpdatedImage.Digest, 360 Tag: lastUpdatedImage.Tag, 361 } 362 } 363 364 func GetProtoEarlierUpdatedImage(repoLastImage *proto_go.RepoLastUpdatedImage, lastImage *proto_go.RepoLastUpdatedImage, 365 ) *proto_go.RepoLastUpdatedImage { 366 if repoLastImage == nil { 367 return lastImage 368 } 369 370 if lastImage == nil || lastImage.LastUpdated == nil { 371 return repoLastImage 372 } 373 374 if repoLastImage.LastUpdated == nil { 375 return lastImage 376 } 377 378 if repoLastImage.LastUpdated.AsTime().Before(lastImage.LastUpdated.AsTime()) { 379 return lastImage 380 } 381 382 return repoLastImage 383 } 384 385 func ref[T any](input T) *T { 386 ref := input 387 388 return &ref 389 } 390 391 func deref[T any](pointer *T, defaultVal T) T { 392 if pointer != nil { 393 return *pointer 394 } 395 396 return defaultVal 397 }