Skip to content

Commit 24879c5

Browse files
authored
fix(search): expose LastPullTimestamp and PushedBy on index ImageSummary (project-zot#3865)
ImageIndex2ImageSummary was missing LastPullTimestamp assignment, causing multi-arch image queries to always return null for this field. Also adds the PushedBy field (already stored in MetaDB) to the GraphQL schema and both conversion paths (manifest and index). Signed-off-by: cainydev <wajo432@gmail.com> Signed-off-by: cainydev <wajo432@gmail.com>
1 parent 2ba0525 commit 24879c5

5 files changed

Lines changed: 103 additions & 28 deletions

File tree

pkg/extensions/search/convert/convert_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,19 +279,21 @@ func TestTaggedTimestamp(t *testing.T) {
279279
Convey("TaggedTimestamp is populated from tag descriptor", func() {
280280
taggedTime := time.Date(2024, time.January, 15, 10, 30, 0, 0, time.UTC)
281281
pushTime := time.Date(2024, time.January, 10, 8, 0, 0, 0, time.UTC)
282+
digestStr := godigest.FromString("sha256:abc123").String()
282283

283284
repoMeta := mTypes.RepoMeta{
284285
Name: "repo",
285286
Tags: map[string]mTypes.Descriptor{
286287
"tag1": {
287-
Digest: "sha256:abc123",
288+
Digest: digestStr,
288289
MediaType: ispec.MediaTypeImageManifest,
289290
TaggedTimestamp: taggedTime,
290291
},
291292
},
292293
Statistics: map[string]mTypes.DescriptorStatistics{
293-
"sha256:abc123": {
294+
digestStr: {
294295
PushTimestamp: pushTime,
296+
PushedBy: "testuser",
295297
},
296298
},
297299
}
@@ -319,6 +321,8 @@ func TestTaggedTimestamp(t *testing.T) {
319321
So(err, ShouldBeNil)
320322
So(imageSummary.TaggedTimestamp, ShouldNotBeNil)
321323
So(*imageSummary.TaggedTimestamp, ShouldEqual, taggedTime)
324+
So(imageSummary.PushedBy, ShouldNotBeNil)
325+
So(*imageSummary.PushedBy, ShouldEqual, "testuser")
322326
})
323327

324328
Convey("TaggedTimestamp falls back to PushTimestamp when zero", func() {
@@ -372,6 +376,7 @@ func TestTaggedTimestamp(t *testing.T) {
372376
Convey("TaggedTimestamp is propagated to nested manifests in ImageIndex", func() {
373377
taggedTime := time.Date(2024, time.January, 15, 10, 30, 0, 0, time.UTC)
374378
pushTime := time.Date(2024, time.January, 10, 8, 0, 0, 0, time.UTC)
379+
lastPullTime := time.Date(2024, time.February, 1, 12, 0, 0, 0, time.UTC)
375380

376381
// Create a multiarch image
377382
multiarchImage := CreateMultiarchWith().Images([]Image{
@@ -392,7 +397,9 @@ func TestTaggedTimestamp(t *testing.T) {
392397
},
393398
Statistics: map[string]mTypes.DescriptorStatistics{
394399
indexDigestStr: {
395-
PushTimestamp: pushTime,
400+
PushTimestamp: pushTime,
401+
LastPullTimestamp: lastPullTime,
402+
PushedBy: "indexuser",
396403
},
397404
},
398405
}
@@ -405,6 +412,10 @@ func TestTaggedTimestamp(t *testing.T) {
405412
So(err, ShouldBeNil)
406413
So(imageSummary.TaggedTimestamp, ShouldNotBeNil)
407414
So(*imageSummary.TaggedTimestamp, ShouldEqual, taggedTime)
415+
So(imageSummary.LastPullTimestamp, ShouldNotBeNil)
416+
So(*imageSummary.LastPullTimestamp, ShouldEqual, lastPullTime)
417+
So(imageSummary.PushedBy, ShouldNotBeNil)
418+
So(*imageSummary.PushedBy, ShouldEqual, "indexuser")
408419

409420
// Verify that nested manifests also have the correct TaggedTimestamp
410421
So(len(imageSummary.Manifests), ShouldBeGreaterThan, 0)

pkg/extensions/search/convert/metadb.go

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -427,10 +427,12 @@ func ImageIndex2ImageSummary(ctx context.Context, fullImageMeta mTypes.FullImage
427427
manifestSummaries = make([]*gql_generated.ManifestSummary, 0, len(fullImageMeta.Manifests))
428428
indexBlobs = map[string]int64{}
429429

430-
indexDigestStr = fullImageMeta.Digest.String()
431-
indexMediaType = ispec.MediaTypeImageIndex
432-
pushTimestamp = fullImageMeta.Statistics.PushTimestamp
433-
taggedTimestamp = fullImageMeta.TaggedTimestamp
430+
indexDigestStr = fullImageMeta.Digest.String()
431+
indexMediaType = ispec.MediaTypeImageIndex
432+
lastPullTimestamp = fullImageMeta.Statistics.LastPullTimestamp
433+
pushTimestamp = fullImageMeta.Statistics.PushTimestamp
434+
pushedBy = fullImageMeta.Statistics.PushedBy
435+
taggedTimestamp = fullImageMeta.TaggedTimestamp
434436
)
435437

436438
// Fallback to PushTimestamp if TaggedTimestamp is not available
@@ -490,27 +492,29 @@ func ImageIndex2ImageSummary(ctx context.Context, fullImageMeta mTypes.FullImage
490492
}
491493

492494
indexSummary := gql_generated.ImageSummary{
493-
RepoName: &repo,
494-
Tag: &tag,
495-
Digest: &indexDigestStr,
496-
MediaType: &indexMediaType,
497-
Manifests: manifestSummaries,
498-
LastUpdated: imageLastUpdated,
499-
IsSigned: &isSigned,
500-
SignatureInfo: signaturesInfo,
501-
Size: ref(strconv.FormatInt(indexSize, 10)),
502-
DownloadCount: ref(fullImageMeta.Statistics.DownloadCount),
503-
PushTimestamp: &pushTimestamp,
504-
TaggedTimestamp: &taggedTimestamp,
505-
Description: &annotations.Description,
506-
Title: &annotations.Title,
507-
Documentation: &annotations.Documentation,
508-
Licenses: &annotations.Licenses,
509-
Labels: &annotations.Labels,
510-
Source: &annotations.Source,
511-
Vendor: &annotations.Vendor,
512-
Authors: &annotations.Authors,
513-
Referrers: getReferrers(fullImageMeta.Referrers),
495+
RepoName: &repo,
496+
Tag: &tag,
497+
Digest: &indexDigestStr,
498+
MediaType: &indexMediaType,
499+
Manifests: manifestSummaries,
500+
LastUpdated: imageLastUpdated,
501+
IsSigned: &isSigned,
502+
SignatureInfo: signaturesInfo,
503+
Size: ref(strconv.FormatInt(indexSize, 10)),
504+
DownloadCount: ref(fullImageMeta.Statistics.DownloadCount),
505+
LastPullTimestamp: &lastPullTimestamp,
506+
PushTimestamp: &pushTimestamp,
507+
PushedBy: &pushedBy,
508+
TaggedTimestamp: &taggedTimestamp,
509+
Description: &annotations.Description,
510+
Title: &annotations.Title,
511+
Documentation: &annotations.Documentation,
512+
Licenses: &annotations.Licenses,
513+
Labels: &annotations.Labels,
514+
Source: &annotations.Source,
515+
Vendor: &annotations.Vendor,
516+
Authors: &annotations.Authors,
517+
Referrers: getReferrers(fullImageMeta.Referrers),
514518
}
515519

516520
return &indexSummary, indexBlobs, nil
@@ -534,6 +538,7 @@ func ImageManifest2ImageSummary(ctx context.Context, fullImageMeta mTypes.FullIm
534538
isSigned = isImageSigned(fullImageMeta.Signatures)
535539
lastPullTimestamp = fullImageMeta.Statistics.LastPullTimestamp
536540
pushTimestamp = fullImageMeta.Statistics.PushTimestamp
541+
pushedBy = fullImageMeta.Statistics.PushedBy
537542
taggedTimestamp = fullImageMeta.TaggedTimestamp
538543
)
539544

@@ -594,6 +599,7 @@ func ImageManifest2ImageSummary(ctx context.Context, fullImageMeta mTypes.FullIm
594599
DownloadCount: &downloadCount,
595600
LastPullTimestamp: &lastPullTimestamp,
596601
PushTimestamp: &pushTimestamp,
602+
PushedBy: &pushedBy,
597603
TaggedTimestamp: &taggedTimestamp,
598604
Description: &annotations.Description,
599605
Title: &annotations.Title,

pkg/extensions/search/gql_generated/generated.go

Lines changed: 52 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/extensions/search/gql_generated/models_gen.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/extensions/search/schema.graphql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ type ImageSummary {
213213
"""
214214
PushTimestamp: Time
215215
"""
216+
The user who pushed the image to the registry
217+
"""
218+
PushedBy: String
219+
"""
216220
Timestamp when the image manifest was tagged (if the data is unavailable it falls back to when the image was pushed to the registry)
217221
"""
218222
TaggedTimestamp: Time

0 commit comments

Comments
 (0)