mirror of
https://github.com/containers/podman.git
synced 2025-12-05 12:52:12 +08:00
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>
This commit is contained in:
@@ -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)
|
||||
imageInfo, layerInfoMap, img, err := runtime.Tree(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printTree(imageInfo, layerInfoMap, img, c.WhatRequires)
|
||||
}
|
||||
|
||||
img, err := runtime.ImageRuntime().NewFromLocal(args[0])
|
||||
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 err
|
||||
}
|
||||
|
||||
// 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(),
|
||||
}
|
||||
|
||||
size, err := img.Size(context.Background())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error while retriving image size")
|
||||
}
|
||||
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 printImageChildren(layerInfoMap, img.TopLayer(), "", true)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user