mirror of
https://github.com/containers/podman.git
synced 2025-09-26 08:14:14 +08:00
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:
206
vendor/github.com/containers/common/libimage/inspect.go
generated
vendored
Normal file
206
vendor/github.com/containers/common/libimage/inspect.go
generated
vendored
Normal file
@ -0,0 +1,206 @@
|
||||
package libimage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/opencontainers/go-digest"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ImageData contains the inspected data of an image.
|
||||
type ImageData struct {
|
||||
ID string `json:"Id"`
|
||||
Digest digest.Digest `json:"Digest"`
|
||||
RepoTags []string `json:"RepoTags"`
|
||||
RepoDigests []string `json:"RepoDigests"`
|
||||
Parent string `json:"Parent"`
|
||||
Comment string `json:"Comment"`
|
||||
Created *time.Time `json:"Created"`
|
||||
Config *ociv1.ImageConfig `json:"Config"`
|
||||
Version string `json:"Version"`
|
||||
Author string `json:"Author"`
|
||||
Architecture string `json:"Architecture"`
|
||||
Os string `json:"Os"`
|
||||
Size int64 `json:"Size"`
|
||||
VirtualSize int64 `json:"VirtualSize"`
|
||||
GraphDriver *DriverData `json:"GraphDriver"`
|
||||
RootFS *RootFS `json:"RootFS"`
|
||||
Labels map[string]string `json:"Labels"`
|
||||
Annotations map[string]string `json:"Annotations"`
|
||||
ManifestType string `json:"ManifestType"`
|
||||
User string `json:"User"`
|
||||
History []ociv1.History `json:"History"`
|
||||
NamesHistory []string `json:"NamesHistory"`
|
||||
HealthCheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"`
|
||||
}
|
||||
|
||||
// DriverData includes data on the storage driver of the image.
|
||||
type DriverData struct {
|
||||
Name string `json:"Name"`
|
||||
Data map[string]string `json:"Data"`
|
||||
}
|
||||
|
||||
// RootFS includes data on the root filesystem of the image.
|
||||
type RootFS struct {
|
||||
Type string `json:"Type"`
|
||||
Layers []digest.Digest `json:"Layers"`
|
||||
}
|
||||
|
||||
// Inspect inspects the image. Use `withSize` to also perform the
|
||||
// comparatively expensive size computation of the image.
|
||||
func (i *Image) Inspect(ctx context.Context, withSize bool) (*ImageData, error) {
|
||||
logrus.Debugf("Inspecting image %s", i.ID())
|
||||
|
||||
if i.cached.completeInspectData != nil {
|
||||
if withSize && i.cached.completeInspectData.Size == int64(-1) {
|
||||
size, err := i.Size()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.cached.completeInspectData.Size = size
|
||||
}
|
||||
return i.cached.completeInspectData, nil
|
||||
}
|
||||
|
||||
// First assemble data that does not depend on the format of the image.
|
||||
info, err := i.inspectInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ociImage, err := i.toOCI(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
parentImage, err := i.Parent(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoTags, err := i.RepoTags()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoDigests, err := i.RepoDigests()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
driverData, err := i.driverData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
size := int64(-1)
|
||||
if withSize {
|
||||
size, err = i.Size()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
data := &ImageData{
|
||||
ID: i.ID(),
|
||||
RepoTags: repoTags,
|
||||
RepoDigests: repoDigests,
|
||||
Created: ociImage.Created,
|
||||
Author: ociImage.Author,
|
||||
Architecture: ociImage.Architecture,
|
||||
Os: ociImage.OS,
|
||||
Config: &ociImage.Config,
|
||||
Version: info.DockerVersion,
|
||||
Size: size,
|
||||
VirtualSize: size, // TODO: they should be different (inherited from Podman)
|
||||
Digest: i.Digest(),
|
||||
Labels: info.Labels,
|
||||
RootFS: &RootFS{
|
||||
Type: ociImage.RootFS.Type,
|
||||
Layers: ociImage.RootFS.DiffIDs,
|
||||
},
|
||||
GraphDriver: driverData,
|
||||
User: ociImage.Config.User,
|
||||
History: ociImage.History,
|
||||
NamesHistory: i.NamesHistory(),
|
||||
}
|
||||
|
||||
if parentImage != nil {
|
||||
data.Parent = parentImage.ID()
|
||||
}
|
||||
|
||||
// Determine the format of the image. How we determine certain data
|
||||
// depends on the format (e.g., Docker v2s2, OCI v1).
|
||||
src, err := i.source(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manifestRaw, manifestType, err := src.GetManifest(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data.ManifestType = manifestType
|
||||
|
||||
switch manifestType {
|
||||
// OCI image
|
||||
case ociv1.MediaTypeImageManifest:
|
||||
var ociManifest ociv1.Manifest
|
||||
if err := json.Unmarshal(manifestRaw, &ociManifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Annotations = ociManifest.Annotations
|
||||
if len(ociImage.History) > 0 {
|
||||
data.Comment = ociImage.History[0].Comment
|
||||
}
|
||||
|
||||
// Docker image
|
||||
case manifest.DockerV2Schema1MediaType, manifest.DockerV2Schema2MediaType:
|
||||
rawConfig, err := i.rawConfigBlob(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var dockerManifest manifest.Schema2V1Image
|
||||
if err := json.Unmarshal(rawConfig, &dockerManifest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data.Comment = dockerManifest.Comment
|
||||
data.HealthCheck = dockerManifest.ContainerConfig.Healthcheck
|
||||
}
|
||||
|
||||
if data.Annotations == nil {
|
||||
// Podman compat
|
||||
data.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
i.cached.completeInspectData = data
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// inspectInfo returns the image inspect info.
|
||||
func (i *Image) inspectInfo(ctx context.Context) (*types.ImageInspectInfo, error) {
|
||||
if i.cached.partialInspectData != nil {
|
||||
return i.cached.partialInspectData, nil
|
||||
}
|
||||
|
||||
ref, err := i.StorageReference()
|
||||
if err != nil {
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
img, err := ref.NewImage(ctx, i.runtime.systemContextCopy())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer img.Close()
|
||||
|
||||
data, err := img.Inspect(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
i.cached.partialInspectData = data
|
||||
return data, nil
|
||||
}
|
Reference in New Issue
Block a user