zotregistry.dev/zot@v1.4.4-0.20240314164342-eec277e14d20/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.dev/zot/pkg/common" 11 proto_go "zotregistry.dev/zot/pkg/meta/proto/gen" 12 mTypes "zotregistry.dev/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: 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[mTypes.ImageDigest]mTypes.DescriptorStatistics, 122 ) map[mTypes.ImageDigest]*proto_go.DescriptorStatistics { 123 results := map[mTypes.ImageDigest]*proto_go.DescriptorStatistics{} 124 125 for digest, stat := range stats { 126 results[digest] = &proto_go.DescriptorStatistics{ 127 DownloadCount: int32(stat.DownloadCount), 128 LastPullTimestamp: timestamppb.New(stat.LastPullTimestamp), 129 PushTimestamp: timestamppb.New(stat.PushTimestamp), 130 PushedBy: stat.PushedBy, 131 } 132 } 133 134 return results 135 } 136 137 func GetProtoPlatforms(platforms []ispec.Platform) []*proto_go.Platform { 138 result := []*proto_go.Platform{} 139 140 for i := range platforms { 141 result = append(result, &proto_go.Platform{ 142 OS: platforms[i].OS, 143 Architecture: platforms[i].Architecture, 144 }) 145 } 146 147 return result 148 } 149 150 func GetProtoReferrers(refs map[string][]mTypes.ReferrerInfo) map[string]*proto_go.ReferrersInfo { 151 results := map[string]*proto_go.ReferrersInfo{} 152 153 for digest, ref := range refs { 154 referrersInfoList := []*proto_go.ReferrerInfo{} 155 156 for _, dbRef := range ref { 157 referrersInfoList = append(referrersInfoList, GetProtoReferrerInfo(dbRef)) 158 } 159 160 results[digest] = &proto_go.ReferrersInfo{List: referrersInfoList} 161 } 162 163 return results 164 } 165 166 func GetProtoSignatures(sigs map[string]mTypes.ManifestSignatures) map[string]*proto_go.ManifestSignatures { 167 results := map[string]*proto_go.ManifestSignatures{} 168 169 for digest, dbSignatures := range sigs { 170 imageSignatures := &proto_go.ManifestSignatures{Map: map[string]*proto_go.SignaturesInfo{}} 171 172 for signatureName, signatureInfo := range dbSignatures { 173 imageSignatures.Map[signatureName] = &proto_go.SignaturesInfo{List: GetProtoSignaturesInfo(signatureInfo)} 174 } 175 176 results[digest] = imageSignatures 177 } 178 179 return results 180 } 181 182 func GetProtoSignaturesInfo(sigsInfo []mTypes.SignatureInfo) []*proto_go.SignatureInfo { 183 results := []*proto_go.SignatureInfo{} 184 185 for _, sigInfo := range sigsInfo { 186 results = append(results, &proto_go.SignatureInfo{ 187 SignatureManifestDigest: sigInfo.SignatureManifestDigest, 188 LayersInfo: GetProtoLayersInfo(sigInfo.LayersInfo), 189 }) 190 } 191 192 return results 193 } 194 195 func GetProtoLayersInfo(layersInfo []mTypes.LayerInfo) []*proto_go.LayersInfo { 196 result := make([]*proto_go.LayersInfo, 0, len(layersInfo)) 197 198 for _, layerInfo := range layersInfo { 199 result = append(result, &proto_go.LayersInfo{ 200 LayerDigest: layerInfo.LayerDigest, 201 LayerContent: layerInfo.LayerContent, 202 SignatureKey: layerInfo.SignatureKey, 203 Signer: layerInfo.Signer, 204 Date: timestamppb.New(layerInfo.Date), 205 }) 206 } 207 208 return result 209 } 210 211 func getProtoManifestLayers(layers []ispec.Descriptor) []*proto_go.Descriptor { 212 protoLayers := []*proto_go.Descriptor{} 213 214 for _, layer := range layers { 215 layer := layer 216 217 protoLayers = append(protoLayers, getProtoDesc(&layer)) 218 } 219 220 return protoLayers 221 } 222 223 func getProtoDesc(descriptor *ispec.Descriptor) *proto_go.Descriptor { 224 if descriptor == nil { 225 return nil 226 } 227 228 return &proto_go.Descriptor{ 229 MediaType: descriptor.MediaType, 230 Digest: descriptor.Digest.String(), 231 Size: descriptor.Size, 232 URLs: descriptor.URLs, 233 Annotations: descriptor.Annotations, 234 Data: descriptor.Data, 235 Platform: GetProtoPlatform(descriptor.Platform), 236 ArtifactType: &descriptor.ArtifactType, 237 } 238 } 239 240 func getProtoManifestList(manifests []ispec.Descriptor) []*proto_go.Descriptor { 241 result := make([]*proto_go.Descriptor, 0, len(manifests)) 242 243 for _, manifest := range manifests { 244 result = append(result, &proto_go.Descriptor{ 245 MediaType: manifest.MediaType, 246 Digest: manifest.Digest.String(), 247 Size: manifest.Size, 248 URLs: manifest.URLs, 249 Annotations: manifest.Annotations, 250 Data: manifest.Data, 251 Platform: GetProtoPlatform(manifest.Platform), 252 ArtifactType: ref(manifest.ArtifactType), 253 }) 254 } 255 256 return result 257 } 258 259 func GetProtoPlatform(platform *ispec.Platform) *proto_go.Platform { 260 if platform == nil { 261 return nil 262 } 263 264 return &proto_go.Platform{ 265 Architecture: platform.Architecture, 266 OS: platform.OS, 267 OSVersion: ref(platform.OSVersion), 268 OSFeatures: platform.OSFeatures, 269 Variant: ref(platform.Variant), 270 } 271 } 272 273 func getProtoHistory(historySlice []ispec.History) []*proto_go.History { 274 protoHistory := []*proto_go.History{} 275 276 for _, history := range historySlice { 277 history := history 278 279 protoHistory = append(protoHistory, &proto_go.History{ 280 Created: GetProtoTime(history.Created), 281 CreatedBy: &history.CreatedBy, 282 Author: &history.Author, 283 Comment: &history.Comment, 284 EmptyLayer: &history.EmptyLayer, 285 }) 286 } 287 288 return protoHistory 289 } 290 291 func getProtoDiffIDs(digests []godigest.Digest) []string { 292 digestsStr := []string{} 293 294 for _, digest := range digests { 295 digestsStr = append(digestsStr, digest.String()) 296 } 297 298 return digestsStr 299 } 300 301 func getProtoExposedPorts(exposedPorts map[string]struct{}) map[string]*proto_go.EmptyMessage { 302 protoPorts := map[string]*proto_go.EmptyMessage{} 303 304 for i := range exposedPorts { 305 protoPorts[i] = &proto_go.EmptyMessage{} 306 } 307 308 return protoPorts 309 } 310 311 func getProtoConfigVolumes(volumes map[string]struct{}) map[string]*proto_go.EmptyMessage { 312 protoVolumes := map[string]*proto_go.EmptyMessage{} 313 314 for i := range volumes { 315 protoVolumes[i] = &proto_go.EmptyMessage{} 316 } 317 318 return protoVolumes 319 } 320 321 func GetProtoReferrerInfo(referrer mTypes.ReferrerInfo) *proto_go.ReferrerInfo { 322 return &proto_go.ReferrerInfo{ 323 Digest: referrer.Digest, 324 MediaType: referrer.MediaType, 325 ArtifactType: referrer.ArtifactType, 326 Size: int64(referrer.Size), 327 Annotations: referrer.Annotations, 328 } 329 } 330 331 func GetProtoTime(time *time.Time) *timestamppb.Timestamp { 332 if time == nil { 333 return nil 334 } 335 336 return timestamppb.New(*time) 337 } 338 339 func GetProtoTags(tags map[mTypes.Tag]mTypes.Descriptor) map[mTypes.Tag]*proto_go.TagDescriptor { 340 resultMap := map[mTypes.Tag]*proto_go.TagDescriptor{} 341 342 for tag, tagDescriptor := range tags { 343 resultMap[tag] = &proto_go.TagDescriptor{ 344 Digest: tagDescriptor.Digest, 345 MediaType: tagDescriptor.MediaType, 346 } 347 } 348 349 return resultMap 350 } 351 352 func GetProtoLastUpdatedImage(lastUpdatedImage *mTypes.LastUpdatedImage) *proto_go.RepoLastUpdatedImage { 353 if lastUpdatedImage == nil { 354 return nil 355 } 356 357 return &proto_go.RepoLastUpdatedImage{ 358 LastUpdated: GetProtoTime(lastUpdatedImage.LastUpdated), 359 MediaType: lastUpdatedImage.MediaType, 360 Digest: lastUpdatedImage.Digest, 361 Tag: lastUpdatedImage.Tag, 362 } 363 } 364 365 func GetProtoEarlierUpdatedImage(repoLastImage *proto_go.RepoLastUpdatedImage, lastImage *proto_go.RepoLastUpdatedImage, 366 ) *proto_go.RepoLastUpdatedImage { 367 if repoLastImage == nil { 368 return lastImage 369 } 370 371 if lastImage == nil || lastImage.LastUpdated == nil { 372 return repoLastImage 373 } 374 375 if repoLastImage.LastUpdated == nil { 376 return lastImage 377 } 378 379 if repoLastImage.LastUpdated.AsTime().Before(lastImage.LastUpdated.AsTime()) { 380 return lastImage 381 } 382 383 return repoLastImage 384 } 385 386 func ref[T any](input T) *T { 387 ref := input 388 389 return &ref 390 } 391 392 func deref[T any](pointer *T, defaultVal T) T { 393 if pointer != nil { 394 return *pointer 395 } 396 397 return defaultVal 398 }