diff options
author | Valentin Rothberg <rothberg@redhat.com> | 2021-04-22 08:01:12 +0200 |
---|---|---|
committer | Valentin Rothberg <rothberg@redhat.com> | 2021-05-05 11:30:12 +0200 |
commit | 0f7d54b0260c1be992ee3b9cee359ef3a9e8bd21 (patch) | |
tree | 192e52054de2abf0c92d83ecdbc71d498c2ec947 /libpod/image/layer_tree.go | |
parent | 8eefca5a257121b177562742c972e39e1686140d (diff) | |
download | podman-0f7d54b0260c1be992ee3b9cee359ef3a9e8bd21.tar.gz podman-0f7d54b0260c1be992ee3b9cee359ef3a9e8bd21.tar.bz2 podman-0f7d54b0260c1be992ee3b9cee359ef3a9e8bd21.zip |
migrate Podman to containers/common/libimage
Migrate the Podman code base over to `common/libimage` which replaces
`libpod/image` and a lot of glue code entirely.
Note that I tried to leave bread crumbs for changed tests.
Miscellaneous changes:
* Some errors yield different messages which required to alter some
tests.
* I fixed some pre-existing issues in the code. Others were marked as
`//TODO`s to prevent the PR from exploding.
* The `NamesHistory` of an image is returned as is from the storage.
Previously, we did some filtering which I think is undesirable.
Instead we should return the data as stored in the storage.
* Touched handlers use the ABI interfaces where possible.
* Local image resolution: previously Podman would match "foo" on
"myfoo". This behaviour has been changed and Podman will now
only match on repository boundaries such that "foo" would match
"my/foo" but not "myfoo". I consider the old behaviour to be a
bug, at the very least an exotic corner case.
* Futhermore, "foo:none" does *not* resolve to a local image "foo"
without tag anymore. It's a hill I am (almost) willing to die on.
* `image prune` prints the IDs of pruned images. Previously, in some
cases, the names were printed instead. The API clearly states ID,
so we should stick to it.
* Compat endpoint image removal with _force_ deletes the entire not
only the specified tag.
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
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 -} |