mirror of https://github.com/containers/podman.git
Handle images which contain no layers
This fixes some of our handling of images which have no layers, i.e., those whose TopLayer is set to an empty value. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
parent
8e79de2848
commit
1ebb84b58e
|
@ -72,7 +72,11 @@ func printTree(imageInfo *image.InfoImage, layerInfoMap map[string]*image.LayerI
|
|||
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 img.TopLayer() != "" {
|
||||
fmt.Printf("Image Layers\n")
|
||||
} else {
|
||||
fmt.Printf("No Image Layers\n")
|
||||
}
|
||||
|
||||
if !whatRequires {
|
||||
// fill imageInfo with layers associated with image.
|
||||
|
|
|
@ -660,11 +660,7 @@ func (i *Image) Size(ctx context.Context) (*uint64, error) {
|
|||
|
||||
// DriverData gets the driver data from the store on a layer
|
||||
func (i *Image) DriverData() (*driver.Data, error) {
|
||||
topLayer, err := i.Layer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return driver.GetDriverData(i.imageruntime.store, topLayer.ID)
|
||||
return driver.GetDriverData(i.imageruntime.store, i.TopLayer())
|
||||
}
|
||||
|
||||
// Layer returns the image's top layer
|
||||
|
@ -693,13 +689,17 @@ func (i *Image) History(ctx context.Context) ([]*History, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// Use our layers list to find images that use one of them as its
|
||||
// Use our layers list to find images that use any of them (or no
|
||||
// layer, since every base layer is derived from an empty layer) as its
|
||||
// topmost layer.
|
||||
interestingLayers := make(map[string]bool)
|
||||
layer, err := i.imageruntime.store.Layer(i.TopLayer())
|
||||
if err != nil {
|
||||
var layer *storage.Layer
|
||||
if i.TopLayer() != "" {
|
||||
if layer, err = i.imageruntime.store.Layer(i.TopLayer()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
interestingLayers[""] = true
|
||||
for layer != nil {
|
||||
interestingLayers[layer.ID] = true
|
||||
if layer.Parent == "" {
|
||||
|
@ -795,27 +795,6 @@ func (i *Image) History(ctx context.Context) ([]*History, error) {
|
|||
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"
|
||||
func (i *Image) Dangling() bool {
|
||||
return len(i.Names()) == 0
|
||||
|
@ -1143,14 +1122,16 @@ func areParentAndChild(parent, child *imgspecv1.Image) bool {
|
|||
|
||||
// GetParent returns the image ID of the parent. Return nil if a parent is not found.
|
||||
func (i *Image) GetParent(ctx context.Context) (*Image, error) {
|
||||
var childLayer *storage.Layer
|
||||
images, err := i.imageruntime.GetImages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
childLayer, err := i.imageruntime.store.Layer(i.TopLayer())
|
||||
if err != nil {
|
||||
if i.TopLayer() != "" {
|
||||
if childLayer, err = i.imageruntime.store.Layer(i.TopLayer()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// fetch the configuration for the child image
|
||||
child, err := i.ociv1Image(ctx)
|
||||
if err != nil {
|
||||
|
@ -1161,12 +1142,24 @@ func (i *Image) GetParent(ctx context.Context) (*Image, error) {
|
|||
continue
|
||||
}
|
||||
candidateLayer := img.TopLayer()
|
||||
// as a child, our top layer is either the candidate parent's
|
||||
// layer, or one that's derived from it, so skip over any
|
||||
// candidate image where we know that isn't the case
|
||||
// as a child, our top layer, if we have one, is either the
|
||||
// candidate parent's layer, or one that's derived from it, so
|
||||
// skip over any candidate image where we know that isn't the
|
||||
// case
|
||||
if childLayer != nil {
|
||||
// The child has at least one layer, so a parent would
|
||||
// have a top layer that's either the same as the child's
|
||||
// top layer or the top layer's recorded parent layer,
|
||||
// which could be an empty value.
|
||||
if candidateLayer != childLayer.Parent && candidateLayer != childLayer.ID {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// The child has no layers, but the candidate does.
|
||||
if candidateLayer != "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// fetch the configuration for the candidate image
|
||||
candidate, err := img.ociv1Image(ctx)
|
||||
if err != nil {
|
||||
|
@ -1204,6 +1197,13 @@ func (i *Image) getChildren(ctx context.Context, max int) ([]string, error) {
|
|||
if img.ID() == i.ID() {
|
||||
continue
|
||||
}
|
||||
if img.TopLayer() == "" {
|
||||
if parentLayer != "" {
|
||||
// this image has no layers, but we do, so
|
||||
// it can't be derived from this one
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
candidateLayer, err := img.Layer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1213,6 +1213,7 @@ func (i *Image) getChildren(ctx context.Context, max int) ([]string, error) {
|
|||
if candidateLayer.Parent != parentLayer && candidateLayer.ID != parentLayer {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// fetch the configuration for the candidate image
|
||||
candidate, err := img.ociv1Image(ctx)
|
||||
if err != nil {
|
||||
|
@ -1443,6 +1444,7 @@ func GetLayersMapWithImageInfo(imageruntime *Runtime) (map[string]*LayerInfo, er
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
layerInfoMap[""] = &LayerInfo{}
|
||||
for _, img := range imgs {
|
||||
e, ok := layerInfoMap[img.TopLayer]
|
||||
if !ok {
|
||||
|
|
Loading…
Reference in New Issue