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>
This commit is contained in:
Valentin Rothberg
2021-04-22 08:01:12 +02:00
parent 8eefca5a25
commit 0f7d54b026
190 changed files with 8669 additions and 7743 deletions

View File

@ -0,0 +1,126 @@
package libimage
import (
"context"
"time"
)
// ImageDiskUsage reports the total size of an image. That is the size
type ImageDiskUsage struct {
// Number of containers using the image.
Containers int
// ID of the image.
ID string
// Repository of the image.
Repository string
// Tag of the image.
Tag string
// Created time stamp.
Created time.Time
// The amount of space that an image shares with another one (i.e. their common data).
SharedSize int64
// The the amount of space that is only used by a given image.
UniqueSize int64
// Sum of shared an unique size.
Size int64
}
// DiskUsage calculates the disk usage for each image in the local containers
// storage. Note that a single image may yield multiple usage reports, one for
// each repository tag.
func (r *Runtime) DiskUsage(ctx context.Context) ([]ImageDiskUsage, error) {
layerTree, err := r.layerTree()
if err != nil {
return nil, err
}
images, err := r.ListImages(ctx, nil, nil)
if err != nil {
return nil, err
}
var allUsages []ImageDiskUsage
for _, image := range images {
usages, err := diskUsageForImage(ctx, image, layerTree)
if err != nil {
return nil, err
}
allUsages = append(allUsages, usages...)
}
return allUsages, err
}
// diskUsageForImage returns the disk-usage baseistics for the specified image.
func diskUsageForImage(ctx context.Context, image *Image, tree *layerTree) ([]ImageDiskUsage, error) {
base := ImageDiskUsage{
ID: image.ID(),
Created: image.Created(),
Repository: "<none>",
Tag: "<none>",
}
// Shared, unique and total size.
parent, err := tree.parent(ctx, image)
if err != nil {
return nil, err
}
childIDs, err := tree.children(ctx, image, false)
if err != nil {
return nil, err
}
// Optimistically set unique size to the full size of the image.
size, err := image.Size()
if err != nil {
return nil, err
}
base.UniqueSize = size
if len(childIDs) > 0 {
// If we have children, we share everything.
base.SharedSize = base.UniqueSize
base.UniqueSize = 0
} else if parent != nil {
// If we have no children but a parent, remove the parent
// (shared) size from the unique one.
size, err := parent.Size()
if err != nil {
return nil, err
}
base.UniqueSize -= size
base.SharedSize = size
}
base.Size = base.SharedSize + base.UniqueSize
// Number of containers using the image.
containers, err := image.Containers()
if err != nil {
return nil, err
}
base.Containers = len(containers)
repoTags, err := image.NamedRepoTags()
if err != nil {
return nil, err
}
if len(repoTags) == 0 {
return []ImageDiskUsage{base}, nil
}
pairs, err := ToNameTagPairs(repoTags)
if err != nil {
return nil, err
}
results := make([]ImageDiskUsage, len(pairs))
for i, pair := range pairs {
res := base
res.Repository = pair.Name
res.Tag = pair.Tag
results[i] = res
}
return results, nil
}