diff options
Diffstat (limited to 'libpod/image/layer_tree.go')
-rw-r--r-- | libpod/image/layer_tree.go | 239 |
1 files changed, 0 insertions, 239 deletions
diff --git a/libpod/image/layer_tree.go b/libpod/image/layer_tree.go deleted file mode 100644 index aa3084449..000000000 --- a/libpod/image/layer_tree.go +++ /dev/null @@ -1,239 +0,0 @@ -package image - -import ( - "context" - - ociv1 "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" -) - -// layerTree is an internal representation of local layers. -type layerTree struct { - // nodes is the actual layer tree with layer IDs being keys. - nodes map[string]*layerNode - // ociCache is a cache for Image.ID -> OCI Image. Translations are done - // on-demand. - ociCache map[string]*ociv1.Image -} - -// node returns a layerNode for the specified layerID. -func (t *layerTree) node(layerID string) *layerNode { - node, exists := t.nodes[layerID] - if !exists { - node = &layerNode{} - t.nodes[layerID] = node - } - return node -} - -// toOCI returns an OCI image for the specified image. -func (t *layerTree) toOCI(ctx context.Context, i *Image) (*ociv1.Image, error) { - var err error - oci, exists := t.ociCache[i.ID()] - if !exists { - oci, err = i.ociv1Image(ctx) - if err == nil { - t.ociCache[i.ID()] = oci - } - } - return oci, err -} - -// layerNode is a node in a layerTree. It's ID is the key in a layerTree. -type layerNode struct { - children []*layerNode - images []*Image - parent *layerNode -} - -// layerTree extracts a layerTree from the layers in the local storage and -// relates them to the specified images. -func (ir *Runtime) layerTree() (*layerTree, error) { - layers, err := ir.store.Layers() - if err != nil { - return nil, err - } - - images, err := ir.GetImages() - if err != nil { - return nil, err - } - - tree := layerTree{ - nodes: make(map[string]*layerNode), - ociCache: make(map[string]*ociv1.Image), - } - - // First build a tree purely based on layer information. - for _, layer := range layers { - node := tree.node(layer.ID) - if layer.Parent == "" { - continue - } - parent := tree.node(layer.Parent) - node.parent = parent - parent.children = append(parent.children, node) - } - - // Now assign the images to each (top) layer. - for i := range images { - img := images[i] // do not leak loop variable outside the scope - topLayer := img.TopLayer() - if topLayer == "" { - continue - } - node, exists := tree.nodes[topLayer] - if !exists { - // Note: erroring out in this case has turned out having been a - // mistake. Users may not be able to recover, so we're now - // throwing a warning to guide them to resolve the issue and - // turn the errors non-fatal. - logrus.Warnf("Top layer %s of image %s not found in layer tree. The storage may be corrupted, consider running `podman system reset`.", topLayer, img.ID()) - continue - } - node.images = append(node.images, img) - } - - return &tree, nil -} - -// children returns the image IDs of children . Child images are images -// with either the same top layer as parent or parent being the true parent -// layer. Furthermore, the history of the parent and child images must match -// with the parent having one history item less. -// If all is true, all images are returned. Otherwise, the first image is -// returned. -func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]string, error) { - if parent.TopLayer() == "" { - return nil, nil - } - - var children []string - - parentNode, exists := t.nodes[parent.TopLayer()] - if !exists { - // Note: erroring out in this case has turned out having been a - // mistake. Users may not be able to recover, so we're now - // throwing a warning to guide them to resolve the issue and - // turn the errors non-fatal. - logrus.Warnf("Layer %s not found in layer. The storage may be corrupted, consider running `podman system reset`.", parent.TopLayer()) - return children, nil - } - - parentID := parent.ID() - parentOCI, err := t.toOCI(ctx, parent) - if err != nil { - return nil, err - } - - // checkParent returns true if child and parent are in such a relation. - checkParent := func(child *Image) (bool, error) { - if parentID == child.ID() { - return false, nil - } - childOCI, err := t.toOCI(ctx, child) - if err != nil { - return false, err - } - // History check. - return areParentAndChild(parentOCI, childOCI), nil - } - - // addChildrenFrom adds child images of parent to children. Returns - // true if any image is a child of parent. - addChildrenFromNode := func(node *layerNode) (bool, error) { - foundChildren := false - for _, childImage := range node.images { - isChild, err := checkParent(childImage) - if err != nil { - return foundChildren, err - } - if isChild { - foundChildren = true - children = append(children, childImage.ID()) - if all { - return foundChildren, nil - } - } - } - return foundChildren, nil - } - - // First check images where parent's top layer is also the parent - // layer. - for _, childNode := range parentNode.children { - found, err := addChildrenFromNode(childNode) - if err != nil { - return nil, err - } - if found && all { - return children, nil - } - } - - // Now check images with the same top layer. - if _, err := addChildrenFromNode(parentNode); err != nil { - return nil, err - } - - return children, nil -} - -// parent returns the parent image or nil if no parent image could be found. -func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { - if child.TopLayer() == "" { - return nil, nil - } - - node, exists := t.nodes[child.TopLayer()] - if !exists { - // Note: erroring out in this case has turned out having been a - // mistake. Users may not be able to recover, so we're now - // throwing a warning to guide them to resolve the issue and - // turn the errors non-fatal. - logrus.Warnf("Layer %s not found in layer. The storage may be corrupted, consider running `podman system reset`.", child.TopLayer()) - return nil, nil - } - - childOCI, err := t.toOCI(ctx, child) - if err != nil { - return nil, err - } - - // Check images from the parent node (i.e., parent layer) and images - // with the same layer (i.e., same top layer). - childID := child.ID() - images := node.images - if node.parent != nil { - images = append(images, node.parent.images...) - } - for _, parent := range images { - if parent.ID() == childID { - continue - } - parentOCI, err := t.toOCI(ctx, parent) - if err != nil { - return nil, err - } - // History check. - if areParentAndChild(parentOCI, childOCI) { - return parent, nil - } - } - - return nil, nil -} - -// hasChildrenAndParent returns true if the specified image has children and a -// parent. -func (t *layerTree) hasChildrenAndParent(ctx context.Context, i *Image) (bool, error) { - children, err := t.children(ctx, i, false) - if err != nil { - return false, err - } - if len(children) == 0 { - return false, nil - } - parent, err := t.parent(ctx, i) - return parent != nil, err -} |