mirror of
https://github.com/containers/podman.git
synced 2025-05-29 06:03:25 +08:00
Migrate podman inspect and tag to image library
Signed-off-by: baude <bbaude@redhat.com> Closes: #525 Approved by: baude
This commit is contained in:
@ -180,7 +180,7 @@ func createCmd(c *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := libpod.GetImageData(newImage)
|
||||
data, err := newImage.Inspect()
|
||||
createConfig, err := parseCreateOpts(c, runtime, newImage.Names()[0], data)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -133,7 +133,7 @@ func iterateInput(c *cli.Context, args []string, runtime *libpod.Runtime, inspec
|
||||
inspectError = errors.Wrapf(err, "error getting image %q", input)
|
||||
break
|
||||
}
|
||||
data, err = libpod.GetImageData(image)
|
||||
data, err = image.Inspect()
|
||||
if err != nil {
|
||||
inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
|
||||
break
|
||||
@ -146,7 +146,7 @@ func iterateInput(c *cli.Context, args []string, runtime *libpod.Runtime, inspec
|
||||
inspectError = errors.Wrapf(err, "error getting image %q", input)
|
||||
break
|
||||
}
|
||||
data, err = libpod.GetImageData(image)
|
||||
data, err = image.Inspect()
|
||||
if err != nil {
|
||||
inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
|
||||
break
|
||||
|
@ -54,7 +54,7 @@ func runCmd(c *cli.Context) error {
|
||||
rtc := runtime.GetConfig()
|
||||
newImage, err := runtime.ImageRuntime().New(c.Args()[0], rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{})
|
||||
|
||||
data, err := libpod.GetImageData(newImage)
|
||||
data, err := newImage.Inspect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,10 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/containers/image/docker/reference"
|
||||
"github.com/containers/storage"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/libpod"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@ -30,51 +27,15 @@ func tagCmd(c *cli.Context) error {
|
||||
}
|
||||
defer runtime.Shutdown(false)
|
||||
|
||||
newImage := runtime.NewImage(args[0])
|
||||
newImage.GetLocalImageName()
|
||||
|
||||
img, err := runtime.GetImage(newImage.LocalName)
|
||||
newImage, err := runtime.ImageRuntime().NewFromLocal(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if img == nil {
|
||||
return errors.New("null image")
|
||||
}
|
||||
err = addImageNames(runtime, img, args[1:])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "error adding names %v to image %q", args[1:], args[0])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addImageNames(runtime *libpod.Runtime, image *storage.Image, addNames []string) error {
|
||||
// Add tags to the names if applicable
|
||||
names, err := expandedTags(addNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, name := range names {
|
||||
if err := runtime.TagImage(image, name); err != nil {
|
||||
return errors.Wrapf(err, "error adding name (%v) to image %q", name, image.ID)
|
||||
for _, tagName := range args[1:] {
|
||||
if err := newImage.TagImage(tagName); err != nil {
|
||||
return errors.Wrapf(err, "error adding '%s' to image %q", tagName, newImage.InputName)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func expandedTags(tags []string) ([]string, error) {
|
||||
expandedNames := []string{}
|
||||
for _, tag := range tags {
|
||||
var labelName string
|
||||
name, err := reference.Parse(tag)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing tag %q", name)
|
||||
}
|
||||
if _, ok := name.(reference.NamedTagged); ok {
|
||||
labelName = name.String()
|
||||
} else {
|
||||
labelName = name.String() + ":latest"
|
||||
}
|
||||
expandedNames = append(expandedNames, labelName)
|
||||
}
|
||||
return expandedNames, nil
|
||||
}
|
||||
|
@ -930,7 +930,7 @@ func (c *Container) addImageVolumes(g *generate.Generator) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
imageData, err := GetImageData(newImage)
|
||||
imageData, err := newImage.Inspect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -26,15 +26,23 @@ import (
|
||||
"github.com/projectatomic/libpod/pkg/util"
|
||||
)
|
||||
|
||||
// imageConversions is used to cache image "cast" types
|
||||
type imageConversions struct {
|
||||
imgRef types.Image
|
||||
storeRef types.ImageReference
|
||||
}
|
||||
|
||||
// Image is the primary struct for dealing with images
|
||||
// It is still very much a work in progress
|
||||
type Image struct {
|
||||
// Adding these two structs for now but will cull when we near
|
||||
// completion of this library.
|
||||
imageConversions
|
||||
inspect.ImageData
|
||||
inspect.ImageResult
|
||||
InputName string
|
||||
Local bool
|
||||
inspectInfo *types.ImageInspectInfo
|
||||
InputName string
|
||||
Local bool
|
||||
//runtime *libpod.Runtime
|
||||
image *storage.Image
|
||||
imageruntime *Runtime
|
||||
@ -226,11 +234,22 @@ func (i *Image) ID() string {
|
||||
return i.image.ID
|
||||
}
|
||||
|
||||
// Digest returns the image's Manifest
|
||||
// Digest returns the image's digest
|
||||
func (i *Image) Digest() digest.Digest {
|
||||
return i.image.Digest
|
||||
}
|
||||
|
||||
// Manifest returns the image's manifest as a byte array
|
||||
// and manifest type as a string. The manifest type is
|
||||
// MediaTypeImageManifest from ociv1.
|
||||
func (i *Image) Manifest() ([]byte, string, error) {
|
||||
imgRef, err := i.toImageRef()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return imgRef.Manifest()
|
||||
}
|
||||
|
||||
// Names returns a string array of names associated with the image
|
||||
func (i *Image) Names() []string {
|
||||
return i.image.Names
|
||||
@ -253,20 +272,6 @@ func (i *Image) Remove(force bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func annotations(manifest []byte, manifestType string) map[string]string {
|
||||
annotations := make(map[string]string)
|
||||
switch manifestType {
|
||||
case ociv1.MediaTypeImageManifest:
|
||||
var m ociv1.Manifest
|
||||
if err := json.Unmarshal(manifest, &m); err == nil {
|
||||
for k, v := range m.Annotations {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations
|
||||
}
|
||||
|
||||
// Decompose an Image
|
||||
func (i *Image) Decompose() error {
|
||||
return types2.NotImplementedError
|
||||
@ -349,6 +354,14 @@ func getImageDigest(src types.ImageReference, ctx *types.SystemContext) (string,
|
||||
|
||||
// TagImage adds a tag to the given image
|
||||
func (i *Image) TagImage(tag string) error {
|
||||
decomposedTag, err := decompose(tag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// If the input does not have a tag, we need to add one (latest)
|
||||
if !decomposedTag.isTagged {
|
||||
tag = fmt.Sprintf("%s:%s", tag, decomposedTag.tag)
|
||||
}
|
||||
tags := i.Names()
|
||||
if util.StringInSlice(tag, tags) {
|
||||
return nil
|
||||
@ -426,7 +439,14 @@ func (i *Image) MatchesID(id string) bool {
|
||||
|
||||
// toStorageReference returns a *storageReference from an Image
|
||||
func (i *Image) toStorageReference() (types.ImageReference, error) {
|
||||
return is.Transport.ParseStoreReference(i.imageruntime.store, i.ID())
|
||||
if i.storeRef == nil {
|
||||
storeRef, err := is.Transport.ParseStoreReference(i.imageruntime.store, i.ID())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.storeRef = storeRef
|
||||
}
|
||||
return i.storeRef, nil
|
||||
}
|
||||
|
||||
// ToImageRef returns an image reference type from an image
|
||||
@ -437,15 +457,18 @@ func (i *Image) ToImageRef() (types.Image, error) {
|
||||
|
||||
// toImageRef returns an Image Reference type from an image
|
||||
func (i *Image) toImageRef() (types.Image, error) {
|
||||
ref, err := is.Transport.ParseStoreReference(i.imageruntime.store, "@"+i.ID())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing reference to image %q", i.ID())
|
||||
if i.imgRef == nil {
|
||||
ref, err := is.Transport.ParseStoreReference(i.imageruntime.store, "@"+i.ID())
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error parsing reference to image %q", i.ID())
|
||||
}
|
||||
imgRef, err := ref.NewImage(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading image %q", i.ID())
|
||||
}
|
||||
i.imgRef = imgRef
|
||||
}
|
||||
imgRef, err := ref.NewImage(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading image %q", i.ID())
|
||||
}
|
||||
return imgRef, nil
|
||||
return i.imgRef, nil
|
||||
}
|
||||
|
||||
// sizer knows its size.
|
||||
@ -507,21 +530,116 @@ func (i *Image) Dangling() bool {
|
||||
|
||||
// Labels returns the image's labels
|
||||
func (i *Image) Labels() (map[string]string, error) {
|
||||
sr, err := i.toStorageReference()
|
||||
imgInspect, err := i.imageInspectInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ic, err := sr.NewImage(&types.SystemContext{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imgInspect, err := ic.Inspect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, nil
|
||||
}
|
||||
return imgInspect.Labels, nil
|
||||
}
|
||||
|
||||
// Annotations returns the annotations of an image
|
||||
func (i *Image) Annotations() (map[string]string, error) {
|
||||
manifest, manifestType, err := i.Manifest()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
annotations := make(map[string]string)
|
||||
switch manifestType {
|
||||
case ociv1.MediaTypeImageManifest:
|
||||
var m ociv1.Manifest
|
||||
if err := json.Unmarshal(manifest, &m); err == nil {
|
||||
for k, v := range m.Annotations {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations, nil
|
||||
}
|
||||
|
||||
// ociv1Image converts and image to an imgref and then an
|
||||
// ociv1 image type
|
||||
func (i *Image) ociv1Image() (*ociv1.Image, error) {
|
||||
imgRef, err := i.toImageRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return imgRef.OCIConfig()
|
||||
}
|
||||
|
||||
func (i *Image) imageInspectInfo() (*types.ImageInspectInfo, error) {
|
||||
if i.inspectInfo == nil {
|
||||
sr, err := i.toStorageReference()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ic, err := sr.NewImage(&types.SystemContext{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imgInspect, err := ic.Inspect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
i.inspectInfo = imgInspect
|
||||
}
|
||||
return i.inspectInfo, nil
|
||||
}
|
||||
|
||||
// Inspect returns an image's inspect data
|
||||
func (i *Image) Inspect() (*inspect.ImageData, error) {
|
||||
ociv1Img, err := i.ociv1Image()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info, err := i.imageInspectInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
annotations, err := i.Annotations()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
size, err := i.Size()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var repoDigests []string
|
||||
for _, name := range i.Names() {
|
||||
repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+i.Digest().String())
|
||||
}
|
||||
|
||||
driver, err := i.DriverData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data := &inspect.ImageData{
|
||||
ID: i.ID(),
|
||||
RepoTags: i.Names(),
|
||||
RepoDigests: repoDigests,
|
||||
Comment: ociv1Img.History[0].Comment,
|
||||
Created: ociv1Img.Created,
|
||||
Author: ociv1Img.Author,
|
||||
Architecture: ociv1Img.Architecture,
|
||||
Os: ociv1Img.OS,
|
||||
ContainerConfig: &ociv1Img.Config,
|
||||
Version: info.DockerVersion,
|
||||
Size: int64(*size),
|
||||
VirtualSize: int64(*size),
|
||||
Annotations: annotations,
|
||||
Digest: i.Digest(),
|
||||
Labels: info.Labels,
|
||||
RootFS: &inspect.RootFS{
|
||||
Type: ociv1Img.RootFS.Type,
|
||||
Layers: ociv1Img.RootFS.DiffIDs,
|
||||
},
|
||||
GraphDriver: driver,
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// Import imports and image into the store and returns an image
|
||||
func Import(path, reference string, writer io.Writer, signingOptions SigningOptions, imageConfig ociv1.Image, runtime *Runtime) (*Image, error) {
|
||||
file := TarballTransport + ":" + path
|
||||
|
@ -1,89 +0,0 @@
|
||||
package libpod
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/projectatomic/libpod/libpod/image"
|
||||
"github.com/projectatomic/libpod/pkg/inspect"
|
||||
)
|
||||
|
||||
// GetImageData returns an image's inspect data
|
||||
func GetImageData(img *image.Image) (*inspect.ImageData, error) {
|
||||
imgRef, err := img.ToImageRef()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size, err := imgRef.Size()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
manifest, manifestType, err := imgRef.Manifest()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
|
||||
}
|
||||
imgDigest := digest.Digest("")
|
||||
if len(manifest) > 0 {
|
||||
imgDigest = digest.Canonical.FromBytes(manifest)
|
||||
}
|
||||
annotations := annotations(manifest, manifestType)
|
||||
|
||||
ociv1Img, err := imgRef.OCIConfig()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting oci image info %q", img.ID)
|
||||
}
|
||||
info, err := imgRef.Inspect()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "error getting image info %q", img.ID)
|
||||
}
|
||||
|
||||
var repoDigests []string
|
||||
for _, name := range img.Names() {
|
||||
repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+imgDigest.String())
|
||||
}
|
||||
|
||||
driver, err := img.DriverData()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
data := &inspect.ImageData{
|
||||
ID: img.ID(),
|
||||
RepoTags: img.Names(),
|
||||
RepoDigests: repoDigests,
|
||||
Comment: ociv1Img.History[0].Comment,
|
||||
Created: ociv1Img.Created,
|
||||
Author: ociv1Img.Author,
|
||||
Architecture: ociv1Img.Architecture,
|
||||
Os: ociv1Img.OS,
|
||||
ContainerConfig: &ociv1Img.Config,
|
||||
Version: info.DockerVersion,
|
||||
Size: size,
|
||||
VirtualSize: size,
|
||||
Annotations: annotations,
|
||||
Digest: imgDigest,
|
||||
Labels: info.Labels,
|
||||
RootFS: &inspect.RootFS{
|
||||
Type: ociv1Img.RootFS.Type,
|
||||
Layers: ociv1Img.RootFS.DiffIDs,
|
||||
},
|
||||
GraphDriver: driver,
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func annotations(manifest []byte, manifestType string) map[string]string {
|
||||
annotations := make(map[string]string)
|
||||
switch manifestType {
|
||||
case ociv1.MediaTypeImageManifest:
|
||||
var m ociv1.Manifest
|
||||
if err := json.Unmarshal(manifest, &m); err == nil {
|
||||
for k, v := range m.Annotations {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
return annotations
|
||||
}
|
@ -961,7 +961,7 @@ func (r *Runtime) GetImages(params *ImageFilterParams, filters ...ImageFilter) (
|
||||
var imagesFiltered []*image.Image
|
||||
|
||||
for _, img := range images {
|
||||
info, err := GetImageData(img)
|
||||
info, err := img.Inspect()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1062,7 +1062,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
|
||||
params.Label = pair[1]
|
||||
case "before":
|
||||
if img, err := findImageInSlice(images, pair[1]); err == nil {
|
||||
info, err := GetImageData(img)
|
||||
info, err := img.Inspect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -1072,7 +1072,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
|
||||
}
|
||||
case "since":
|
||||
if img, err := findImageInSlice(images, pair[1]); err == nil {
|
||||
info, err := GetImageData(img)
|
||||
info, err := img.Inspect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user