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:
parent
1deb9795c3
commit
40117e8bfe
3 changed files with 43 additions and 40 deletions
|
@ -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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue