Use inspected creation dates

We already parse every image if there's a label filter so that we can
check against the filter, so when we do that, go ahead and read the
OCI-format configuration and inspection data as well, and use an image's
creation date as recorded in inspection data everywhere.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
Nalin Dahyabhai 2017-07-27 13:35:38 -04:00
parent 1deb9795c3
commit 40117e8bfe
3 changed files with 43 additions and 40 deletions

View file

@ -136,14 +136,17 @@ func outputHeader(truncate, digests bool) {
func outputImages(store storage.Store, images []storage.Image, format string, hasTemplate, truncate, digests, quiet bool) error { func outputImages(store storage.Store, images []storage.Image, format string, hasTemplate, truncate, digests, quiet bool) error {
for _, img := range images { for _, img := range images {
createdTime := img.Created.Format("Jan 2, 2006 15:04") createdTime := img.Created
name := "" name := ""
if len(img.Names) > 0 { if len(img.Names) > 0 {
name = img.Names[0] name = img.Names[0]
} }
digest, size, _ := libkpodimage.DigestAndSize(store, img) info, digest, size, _ := libkpodimage.InfoAndDigestAndSize(store, img)
if info != nil {
createdTime = info.Created
}
if quiet { if quiet {
fmt.Printf("%-64s\n", img.ID) fmt.Printf("%-64s\n", img.ID)
@ -155,7 +158,7 @@ func outputImages(store storage.Store, images []storage.Image, format string, ha
ID: img.ID, ID: img.ID,
Name: name, Name: name,
Digest: digest, Digest: digest,
CreatedAt: createdTime, CreatedAt: createdTime.Format("Jan 2, 2006 15:04"),
Size: libkpodimage.FormattedSize(size), Size: libkpodimage.FormattedSize(size),
} }
if hasTemplate { if hasTemplate {

View file

@ -6,6 +6,7 @@ import (
"time" "time"
is "github.com/containers/image/storage" is "github.com/containers/image/storage"
"github.com/containers/image/types"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/libkpod/common" "github.com/kubernetes-incubator/cri-o/libkpod/common"
digest "github.com/opencontainers/go-digest" digest "github.com/opencontainers/go-digest"
@ -65,13 +66,28 @@ func matchesFilter(store storage.Store, image storage.Image, name string, params
if params == nil { if params == nil {
return true return true
} }
storeRef, err := is.Transport.ParseStoreReference(store, "@"+image.ID)
if err != nil {
return false
}
img, err := storeRef.NewImage(nil)
if err != nil {
return false
}
defer img.Close()
info, err := img.Inspect()
if err != nil {
return false
}
if params.dangling != "" && !matchesDangling(name, params.dangling) { if params.dangling != "" && !matchesDangling(name, params.dangling) {
return false return false
} else if params.label != "" && !matchesLabel(image, store, params.label) { } else if params.label != "" && !matchesLabel(info, store, params.label) {
return false return false
} else if !params.beforeImage.IsZero() && !matchesBeforeImage(image, name, params) { } else if !params.beforeImage.IsZero() && !matchesBeforeImage(info, name, params) {
return false return false
} else if !params.sinceImage.IsZero() && !matchesSinceImage(image, name, params) { } else if !params.sinceImage.IsZero() && !matchesSinceImage(info, name, params) {
return false return false
} else if params.referencePattern != "" && !MatchesReference(name, params.referencePattern) { } else if params.referencePattern != "" && !MatchesReference(name, params.referencePattern) {
return false return false
@ -88,21 +104,7 @@ func matchesDangling(name string, dangling string) bool {
return false return false
} }
func matchesLabel(image storage.Image, store storage.Store, label string) bool { func matchesLabel(info *types.ImageInspectInfo, store storage.Store, label string) bool {
storeRef, err := is.Transport.ParseStoreReference(store, "@"+image.ID)
if err != nil {
}
img, err := storeRef.NewImage(nil)
if err != nil {
return false
}
defer img.Close()
info, err := img.Inspect()
if err != nil {
return false
}
pair := strings.SplitN(label, "=", 2) pair := strings.SplitN(label, "=", 2)
for key, value := range info.Labels { for key, value := range info.Labels {
if key == pair[0] { if key == pair[0] {
@ -120,11 +122,8 @@ func matchesLabel(image storage.Image, store storage.Store, label string) bool {
// Returns true if the image was created since the filter image. Returns // Returns true if the image was created since the filter image. Returns
// false otherwise // false otherwise
func matchesBeforeImage(image storage.Image, name string, params *FilterParams) bool { func matchesBeforeImage(info *types.ImageInspectInfo, name string, params *FilterParams) bool {
if params.beforeImage.IsZero() { if info.Created.Before(params.beforeImage) {
return true
}
if image.Created.Before(params.beforeImage) {
return true return true
} }
return false return false
@ -132,11 +131,8 @@ func matchesBeforeImage(image storage.Image, name string, params *FilterParams)
// Returns true if the image was created since the filter image. Returns // Returns true if the image was created since the filter image. Returns
// false otherwise // false otherwise
func matchesSinceImage(image storage.Image, name string, params *FilterParams) bool { func matchesSinceImage(info *types.ImageInspectInfo, name string, params *FilterParams) bool {
if params.sinceImage.IsZero() { if info.Created.After(params.sinceImage) {
return true
}
if image.Created.After(params.sinceImage) {
return true return true
} }
return false return false
@ -212,32 +208,36 @@ func findImageInSlice(images []storage.Image, ref string) (storage.Image, error)
return storage.Image{}, errors.New("could not find image") return storage.Image{}, errors.New("could not find image")
} }
// DigestAndSize returns the size of the image in the given store and the // InfoAndDigestAndSize returns the inspection info and size of the image in the given
// digest of its manifest, if it has one, or "" if it doesn't. // store and the digest of its manifest, if it has one, or "" if it doesn't.
func DigestAndSize(store storage.Store, img storage.Image) (digest.Digest, int64, error) { func InfoAndDigestAndSize(store storage.Store, img storage.Image) (*types.ImageInspectInfo, digest.Digest, int64, error) {
is.Transport.SetStore(store) is.Transport.SetStore(store)
storeRef, err := is.Transport.ParseStoreReference(store, "@"+img.ID) storeRef, err := is.Transport.ParseStoreReference(store, "@"+img.ID)
if err != nil { if err != nil {
return "", -1, errors.Wrapf(err, "error parsing image reference %q", "@"+img.ID) return nil, "", -1, errors.Wrapf(err, "error parsing image reference %q", "@"+img.ID)
} }
imgRef, err := storeRef.NewImage(nil) imgRef, err := storeRef.NewImage(nil)
if err != nil { if err != nil {
return "", -1, errors.Wrapf(err, "error reading image %q", img.ID) return nil, "", -1, errors.Wrapf(err, "error reading image %q", img.ID)
} }
defer imgRef.Close() defer imgRef.Close()
imgSize, err := imgRef.Size() imgSize, err := imgRef.Size()
if err != nil { if err != nil {
return "", -1, errors.Wrapf(err, "error reading size of image %q", img.ID) return nil, "", -1, errors.Wrapf(err, "error reading size of image %q", img.ID)
} }
manifest, _, err := imgRef.Manifest() manifest, _, err := imgRef.Manifest()
if err != nil { if err != nil {
return "", -1, errors.Wrapf(err, "error reading manifest for image %q", img.ID) return nil, "", -1, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
} }
manifestDigest := digest.Digest("") manifestDigest := digest.Digest("")
if len(manifest) > 0 { if len(manifest) > 0 {
manifestDigest = digest.Canonical.FromBytes(manifest) manifestDigest = digest.Canonical.FromBytes(manifest)
} }
return manifestDigest, imgSize, nil info, err := imgRef.Inspect()
if err != nil {
return nil, "", -1, errors.Wrapf(err, "error inspecting image %q", img.ID)
}
return info, manifestDigest, imgSize, nil
} }
// GetImagesMatchingFilter returns a slice of all images in the store that match the provided FilterParams. // GetImagesMatchingFilter returns a slice of all images in the store that match the provided FilterParams.

View file

@ -98,7 +98,7 @@ func GetImageData(store storage.Store, name string) (*ImageData, error) {
return nil, err return nil, err
} }
digest, virtualSize, err := DigestAndSize(store, *img) _, digest, virtualSize, err := InfoAndDigestAndSize(store, *img)
if err != nil { if err != nil {
return nil, err return nil, err
} }