diff options
Diffstat (limited to 'libpod/image')
-rw-r--r-- | libpod/image/image.go | 33 | ||||
-rw-r--r-- | libpod/image/manifests.go | 154 |
2 files changed, 179 insertions, 8 deletions
diff --git a/libpod/image/image.go b/libpod/image/image.go index 43fd52a1a..5f914ed79 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -916,12 +916,7 @@ func (i *Image) imageInspectInfo(ctx context.Context) (*types.ImageInspectInfo, return i.inspectInfo, nil } -// Inspect returns an image's inspect data -func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { - span, _ := opentracing.StartSpanFromContext(ctx, "imageInspect") - span.SetTag("type", "image") - defer span.Finish() - +func (i *Image) inspect(ctx context.Context, calculateSize bool) (*inspect.ImageData, error) { ociv1Img, err := i.ociv1Image(ctx) if err != nil { ociv1Img = &ociv1.Image{} @@ -936,8 +931,10 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { } size := int64(-1) - if usize, err := i.Size(ctx); err == nil { - size = int64(*usize) + if calculateSize { + if usize, err := i.Size(ctx); err == nil { + size = int64(*usize) + } } repoTags, err := i.RepoTags() @@ -1002,6 +999,26 @@ func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { return data, nil } +// Inspect returns an image's inspect data +func (i *Image) Inspect(ctx context.Context) (*inspect.ImageData, error) { + span, _ := opentracing.StartSpanFromContext(ctx, "imageInspect") + + span.SetTag("type", "image") + defer span.Finish() + + return i.inspect(ctx, true) +} + +// InspectNoSize returns an image's inspect data without calculating the size for the image +func (i *Image) InspectNoSize(ctx context.Context) (*inspect.ImageData, error) { + span, _ := opentracing.StartSpanFromContext(ctx, "imageInspectNoSize") + + span.SetTag("type", "image") + defer span.Finish() + + return i.inspect(ctx, false) +} + // Import imports and image into the store and returns an image func (ir *Runtime) Import(ctx context.Context, path, reference string, writer io.Writer, signingOptions SigningOptions, imageConfig ociv1.Image) (*Image, error) { src, err := tarball.Transport.ParseReference(path) diff --git a/libpod/image/manifests.go b/libpod/image/manifests.go new file mode 100644 index 000000000..9dbeb4cc5 --- /dev/null +++ b/libpod/image/manifests.go @@ -0,0 +1,154 @@ +package image + +import ( + "context" + + "github.com/containers/buildah/manifests" + "github.com/containers/image/v5/manifest" + "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/image/v5/types" + "github.com/opencontainers/go-digest" + "github.com/pkg/errors" +) + +// Options for adding a manifest +// swagger:model ManifestAddOpts +type ManifestAddOpts struct { + All bool `json:"all"` + Annotation map[string]string `json:"annotation"` + Arch string `json:"arch"` + Features []string `json:"features"` + Images []string `json:"images"` + OSVersion string `json:"os_version"` + Variant string `json:"variant"` +} + +// InspectManifest returns a dockerized version of the manifest list +func (i *Image) InspectManifest() (*manifest.Schema2List, error) { + list, err := i.getManifestList() + if err != nil { + return nil, err + } + return list.Docker(), nil +} + +// RemoveManifest removes the given digest from the manifest list. +func (i *Image) RemoveManifest(d digest.Digest) (string, error) { + list, err := i.getManifestList() + if err != nil { + return "", err + } + if err := list.Remove(d); err != nil { + return "", err + } + return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "") +} + +// getManifestList is a helper to obtain a manifest list +func (i *Image) getManifestList() (manifests.List, error) { + _, list, err := manifests.LoadFromImage(i.imageruntime.store, i.ID()) + return list, err +} + +// CreateManifestList creates a new manifest list and can optionally add given images +// to the list +func CreateManifestList(rt *Runtime, systemContext types.SystemContext, names []string, imgs []string, all bool) (string, error) { + list := manifests.Create() + opts := ManifestAddOpts{Images: names, All: all} + for _, img := range imgs { + var ref types.ImageReference + newImage, err := rt.NewFromLocal(img) + if err == nil { + ir, err := newImage.toImageRef(context.Background()) + if err != nil { + return "", err + } + if ir == nil { + return "", errors.New("unable to convert image to ImageReference") + } + ref = ir.Reference() + } else { + ref, err = alltransports.ParseImageName(img) + if err != nil { + return "", err + } + } + list, err = addManifestToList(ref, list, systemContext, opts) + if err != nil { + return "", err + } + } + return list.SaveToImage(rt.store, "", names, manifest.DockerV2ListMediaType) +} + +func addManifestToList(ref types.ImageReference, list manifests.List, systemContext types.SystemContext, opts ManifestAddOpts) (manifests.List, error) { + d, err := list.Add(context.Background(), &systemContext, ref, opts.All) + if err != nil { + return nil, err + } + if len(opts.OSVersion) > 0 { + if err := list.SetOSVersion(d, opts.OSVersion); err != nil { + return nil, err + } + } + if len(opts.Features) > 0 { + if err := list.SetFeatures(d, opts.Features); err != nil { + return nil, err + } + } + if len(opts.Arch) > 0 { + if err := list.SetArchitecture(d, opts.Arch); err != nil { + return nil, err + } + } + if len(opts.Variant) > 0 { + if err := list.SetVariant(d, opts.Variant); err != nil { + return nil, err + } + } + if len(opts.Annotation) > 0 { + if err := list.SetAnnotations(&d, opts.Annotation); err != nil { + return nil, err + } + } + return list, err +} + +// AddManifest adds a manifest to a given manifest list. +func (i *Image) AddManifest(systemContext types.SystemContext, opts ManifestAddOpts) (string, error) { + var ( + ref types.ImageReference + ) + newImage, err := i.imageruntime.NewFromLocal(opts.Images[0]) + if err == nil { + ir, err := newImage.toImageRef(context.Background()) + if err != nil { + return "", err + } + ref = ir.Reference() + } else { + ref, err = alltransports.ParseImageName(opts.Images[0]) + if err != nil { + return "", err + } + } + list, err := i.getManifestList() + if err != nil { + return "", err + } + list, err = addManifestToList(ref, list, systemContext, opts) + if err != nil { + return "", err + } + return list.SaveToImage(i.imageruntime.store, i.ID(), nil, "") +} + +// PushManifest pushes a manifest to a destination +func (i *Image) PushManifest(dest types.ImageReference, opts manifests.PushOptions) (digest.Digest, error) { + list, err := i.getManifestList() + if err != nil { + return "", err + } + _, d, err := list.Push(context.Background(), dest, opts) + return d, err +} |