From dc94dbd3c17c9011fc1e851694a2190dcf6c2b3c Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Tue, 2 Apr 2019 10:26:43 -0500
Subject: podman-remote image tree

add the ability for the podman-remote client to be able to print an
image tree.

Signed-off-by: baude <bbaude@redhat.com>
---
 cmd/podman/tree.go                   | 77 ++++++++----------------------------
 cmd/podman/varlink/io.podman.varlink | 10 ++++-
 2 files changed, 25 insertions(+), 62 deletions(-)

(limited to 'cmd')

diff --git a/cmd/podman/tree.go b/cmd/podman/tree.go
index c56e35aef..371e88495 100644
--- a/cmd/podman/tree.go
+++ b/cmd/podman/tree.go
@@ -5,9 +5,9 @@ import (
 	"fmt"
 
 	"github.com/containers/libpod/cmd/podman/cliconfig"
-	"github.com/containers/libpod/cmd/podman/libpodruntime"
 	"github.com/containers/libpod/libpod/image"
-	units "github.com/docker/go-units"
+	"github.com/containers/libpod/pkg/adapter"
+	"github.com/docker/go-units"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -41,16 +41,6 @@ func init() {
 	treeCommand.Flags().BoolVar(&treeCommand.WhatRequires, "whatrequires", false, "Show all child images and layers of the specified image")
 }
 
-// infoImage keep information of Image along with all associated layers
-type infoImage struct {
-	// id of image
-	id string
-	// tags of image
-	tags []string
-	// layers stores all layers of image.
-	layers []image.LayerInfo
-}
-
 func treeCmd(c *cliconfig.TreeValues) error {
 	args := c.InputArgs
 	if len(args) == 0 {
@@ -60,46 +50,33 @@ func treeCmd(c *cliconfig.TreeValues) error {
 		return errors.Errorf("you must provide at most 1 argument")
 	}
 
-	runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+	runtime, err := adapter.GetRuntime(&c.PodmanCommand)
 	if err != nil {
 		return errors.Wrapf(err, "error creating libpod runtime")
 	}
 	defer runtime.Shutdown(false)
-
-	img, err := runtime.ImageRuntime().NewFromLocal(args[0])
+	imageInfo, layerInfoMap, img, err := runtime.Tree(c)
 	if err != nil {
 		return err
 	}
+	return printTree(imageInfo, layerInfoMap, img, c.WhatRequires)
+}
 
-	// Fetch map of image-layers, which is used for printing output.
-	layerInfoMap, err := image.GetLayersMapWithImageInfo(runtime.ImageRuntime())
-	if err != nil {
-		return errors.Wrapf(err, "error while retriving layers of image %q", img.InputName)
-	}
-
-	// Create an imageInfo and fill the image and layer info
-	imageInfo := &infoImage{
-		id:   img.ID(),
-		tags: img.Names(),
-	}
-
+func printTree(imageInfo *image.InfoImage, layerInfoMap map[string]*image.LayerInfo, img *adapter.ContainerImage, whatRequires bool) error {
 	size, err := img.Size(context.Background())
 	if err != nil {
-		return errors.Wrapf(err, "error while retriving image size")
+		return err
 	}
-	fmt.Printf("Image ID: %s\n", imageInfo.id[:12])
-	fmt.Printf("Tags:\t %s\n", imageInfo.tags)
+
+	fmt.Printf("Image ID: %s\n", imageInfo.ID[:12])
+	fmt.Printf("Tags:\t %s\n", imageInfo.Tags)
 	fmt.Printf("Size:\t %v\n", units.HumanSizeWithPrecision(float64(*size), 4))
 	fmt.Printf(fmt.Sprintf("Image Layers\n"))
 
-	if !c.WhatRequires {
+	if !whatRequires {
 		// fill imageInfo with layers associated with image.
 		// the layers will be filled such that
 		// (Start)RootLayer->...intermediate Parent Layer(s)-> TopLayer(End)
-		err := buildImageHierarchyMap(imageInfo, layerInfoMap, img.TopLayer())
-		if err != nil {
-			return err
-		}
 		// Build output from imageInfo into buffer
 		printImageHierarchy(imageInfo)
 
@@ -108,30 +85,8 @@ func treeCmd(c *cliconfig.TreeValues) error {
 		// the layers will be filled such that
 		// (Start)TopLayer->...intermediate Child Layer(s)-> Child TopLayer(End)
 		//             (Forks)... intermediate Child Layer(s) -> Child Top Layer(End)
-		err := printImageChildren(layerInfoMap, img.TopLayer(), "", true)
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
-// Stores hierarchy of images such that all parent layers using which image is built are stored in imageInfo
-// Layers are added such that  (Start)RootLayer->...intermediate Parent Layer(s)-> TopLayer(End)
-func buildImageHierarchyMap(imageInfo *infoImage, layerMap map[string]*image.LayerInfo, layerID string) error {
-	if layerID == "" {
-		return nil
-	}
-	ll, ok := layerMap[layerID]
-	if !ok {
-		return fmt.Errorf("lookup error: layerid  %s not found", layerID)
+		return printImageChildren(layerInfoMap, img.TopLayer(), "", true)
 	}
-	if err := buildImageHierarchyMap(imageInfo, layerMap, ll.ParentID); err != nil {
-		return err
-	}
-
-	imageInfo.layers = append(imageInfo.layers, *ll)
 	return nil
 }
 
@@ -175,14 +130,14 @@ func printImageChildren(layerMap map[string]*image.LayerInfo, layerID string, pr
 }
 
 // prints the layers info of image
-func printImageHierarchy(imageInfo *infoImage) {
-	for count, l := range imageInfo.layers {
+func printImageHierarchy(imageInfo *image.InfoImage) {
+	for count, l := range imageInfo.Layers {
 		var tags string
 		intend := middleItem
 		if len(l.RepoTags) > 0 {
 			tags = fmt.Sprintf(" Top Layer of: %s", l.RepoTags)
 		}
-		if count == len(imageInfo.layers)-1 {
+		if count == len(imageInfo.Layers)-1 {
 			intend = lastItem
 		}
 		fmt.Printf("%s ID: %s Size: %7v%s\n", intend, l.ID[:12], units.HumanSizeWithPrecision(float64(l.Size), 4), tags)
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 2ff06a6f6..92fdcd20f 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -68,7 +68,8 @@ type Image (
   virtualSize: int,
   containers: int,
   labels: [string]string,
-  isParent: bool
+  isParent: bool,
+  topLayer: string
 )
 
 # ImageHistory describes the returned structure from ImageHistory.
@@ -1161,8 +1162,15 @@ method LoadImage(name: string, inputFile: string, quiet: bool, deleteFile: bool)
 # GetEvents returns known libpod events filtered by the options provided.
 method GetEvents(filter: []string, since: string, until: string) -> (events: Event)
 
+# Diff returns a diff between libpod objects
 method Diff(name: string) -> (diffs: []DiffInfo)
 
+# GetLayersMapWithImageInfo is for the development of Podman and should not be used.
+method GetLayersMapWithImageInfo() -> (layerMap: string)
+
+# BuildImageHierarchyMap is for the development of Podman and should not be used.
+method BuildImageHierarchyMap(name: string) -> (imageInfo: string)
+
 # ImageNotFound means the image could not be found by the provided name or ID in local storage.
 error ImageNotFound (id: string, reason: string)
 
-- 
cgit v1.2.3-54-g00ecf