Fetch image/tag creation date from annotations to support cosign

This commit is contained in:
Roman Vynar
2026-02-15 15:56:36 +02:00
parent 98ec88434d
commit 1bfc1911e1
2 changed files with 29 additions and 1 deletions

View File

@@ -204,6 +204,12 @@ func (c *Client) GetImageInfo(imageRef string) (ImageInfo, error) {
return ImageInfo{}, err
}
// Performance notes:
// puller.Get() → 1 API call (fetches manifest)
// descr.Image() → 0 API calls (type conversion)
// img.ConfigFile() → 1 API call (fetches config blob)
// img.Manifest() → 0 API calls (already fetched on puller.Get())
//
if ii.IsImage {
img, err := descr.Image()
if err != nil {
@@ -216,6 +222,9 @@ func (c *Client) GetImageInfo(imageRef string) (ImageInfo, error) {
return ImageInfo{}, err
}
ii.Created = cfg.Created.Time
if cfg.Created.Time.IsZero() {
ii.Created = extractCreatedFromAnnotations(img)
}
ii.Platforms = getPlatform(cfg.Platform())
ii.ConfigFile = structToMap(cfg)
// ImageID is what is shown in the terminal when doing "docker images".
@@ -289,9 +298,28 @@ func (c *Client) GetImageCreated(imageRef string) time.Time {
c.logger.Errorf("Cannot fetch ConfigFile for image reference %s: %s", imageRef, err)
return *zeroTime
}
if cfg.Created.Time.IsZero() {
return extractCreatedFromAnnotations(img)
}
return cfg.Created.Time
}
func extractCreatedFromAnnotations(img v1.Image) time.Time {
// cosign pushes images with zero time in the image config file.
// However, when cosign is used with --record-creation-timestamp it sets creation time
// into Manifest > annotations > org.opencontainers.image.created which can be used.
zeroTime := new(time.Time)
if mf, err := img.Manifest(); err == nil && mf.Annotations != nil {
if createdStr, ok := mf.Annotations["org.opencontainers.image.created"]; ok {
if createdTime, err := time.Parse(time.RFC3339, createdStr); err == nil {
return createdTime
}
}
}
return *zeroTime
}
// SubRepoTagCounts return map with tag counts according to the provided list of repos/sub-repos etc.
func (c *Client) SubRepoTagCounts(repoPath string, repos []string) map[string]int {
counts := map[string]int{}

View File

@@ -105,7 +105,7 @@ func PurgeOldTags(client *Client, purgeDryRun bool, purgeIncludeRepos, purgeExcl
created := client.GetImageCreated(imageRef)
if created.IsZero() {
// Image manifest with zero creation time, e.g. cosign w/o --record-creation-timestamp
logger.Debugf("[%s] tag with zero creation time: %s", repo, tag)
logger.Warnf("[%s] tag with zero creation time: %s", repo, tag)
continue
}
repos[repo] = append(repos[repo], TagData{name: tag, created: created})