summaryrefslogtreecommitdiff
path: root/libpod/image/image.go
diff options
context:
space:
mode:
authorumohnani8 <umohnani@redhat.com>2018-06-21 16:11:59 -0400
committerAtomic Bot <atomic-devel@projectatomic.io>2018-06-22 15:19:34 +0000
commit088d5af87984e8e8348f3b70004d8107df645f73 (patch)
tree6a2400e1660620f8f6291c8aa7822a29543bbc12 /libpod/image/image.go
parent89af35175d97cf90e7336d3c817612fafc68dbdb (diff)
downloadpodman-088d5af87984e8e8348f3b70004d8107df645f73.tar.gz
podman-088d5af87984e8e8348f3b70004d8107df645f73.tar.bz2
podman-088d5af87984e8e8348f3b70004d8107df645f73.zip
Podman history now prints out intermediate image IDs
If the intermediate image exists in the store, podman history will show the IDs of the intermediate image of each layer. Signed-off-by: umohnani8 <umohnani@redhat.com> Closes: #982 Approved by: mheon
Diffstat (limited to 'libpod/image/image.go')
-rw-r--r--libpod/image/image.go78
1 files changed, 74 insertions, 4 deletions
diff --git a/libpod/image/image.go b/libpod/image/image.go
index c8a929074..57eabe2c8 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -608,17 +608,87 @@ func (i *Image) Layer() (*storage.Layer, error) {
return i.imageruntime.store.Layer(i.image.TopLayer)
}
+// History contains the history information of an image
+type History struct {
+ ID string `json:"id"`
+ Created *time.Time `json:"created"`
+ CreatedBy string `json:"createdBy"`
+ Size int64 `json:"size"`
+ Comment string `json:"comment"`
+}
+
// History gets the history of an image and information about its layers
-func (i *Image) History(ctx context.Context) ([]ociv1.History, []types.BlobInfo, error) {
+func (i *Image) History(ctx context.Context) ([]*History, error) {
img, err := i.toImageRef(ctx)
if err != nil {
- return nil, nil, err
+ return nil, err
}
oci, err := img.OCIConfig(ctx)
if err != nil {
- return nil, nil, err
+ return nil, err
+ }
+
+ // Get the IDs of the images making up the history layers
+ // if the images exist locally in the store
+ images, err := i.imageruntime.GetImages()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting images from store")
+ }
+ imageIDs := []string{i.ID()}
+ if err := i.historyLayerIDs(i.TopLayer(), images, &imageIDs); err != nil {
+ return nil, errors.Wrap(err, "error getting image IDs for layers in history")
}
- return oci.History, img.LayerInfos(), nil
+
+ var (
+ imageID string
+ imgIDCount = 0
+ size int64
+ sizeCount = 1
+ allHistory []*History
+ )
+
+ for i := len(oci.History) - 1; i >= 0; i-- {
+ if imgIDCount < len(imageIDs) {
+ imageID = imageIDs[imgIDCount]
+ imgIDCount++
+ } else {
+ imageID = "<missing>"
+ }
+ if !oci.History[i].EmptyLayer {
+ size = img.LayerInfos()[len(img.LayerInfos())-sizeCount].Size
+ sizeCount++
+ }
+ allHistory = append(allHistory, &History{
+ ID: imageID,
+ Created: oci.History[i].Created,
+ CreatedBy: oci.History[i].CreatedBy,
+ Size: size,
+ Comment: oci.History[i].Comment,
+ })
+ }
+
+ return allHistory, nil
+}
+
+// historyLayerIDs goes through the images in store and checks if the top layer of an image
+// is the same as the parent of topLayerID
+func (i *Image) historyLayerIDs(topLayerID string, images []*Image, IDs *[]string) error {
+ for _, image := range images {
+ // Get the layer info of topLayerID
+ layer, err := i.imageruntime.store.Layer(topLayerID)
+ if err != nil {
+ return errors.Wrapf(err, "error getting layer info %q", topLayerID)
+ }
+ // Check if the parent of layer is equal to the image's top layer
+ // If so add the image ID to the list of IDs and find the parent of
+ // the top layer of the image ID added to the list
+ // Since we are checking for parent, each top layer can only have one parent
+ if layer.Parent == image.TopLayer() {
+ *IDs = append(*IDs, image.ID())
+ return i.historyLayerIDs(image.TopLayer(), images, IDs)
+ }
+ }
+ return nil
}
// Dangling returns a bool if the image is "dangling"