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:
baude
2018-03-21 09:55:57 -05:00
committed by Atomic Bot
parent 3428de0672
commit d0835493d5
8 changed files with 166 additions and 176 deletions

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -26,13 +26,21 @@ 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
inspectInfo *types.ImageInspectInfo
InputName string
Local bool
//runtime *libpod.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,6 +457,7 @@ func (i *Image) ToImageRef() (types.Image, error) {
// toImageRef returns an Image Reference type from an image
func (i *Image) toImageRef() (types.Image, error) {
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())
@ -445,7 +466,9 @@ func (i *Image) toImageRef() (types.Image, error) {
if err != nil {
return nil, errors.Wrapf(err, "error reading image %q", i.ID())
}
return imgRef, nil
i.imgRef = imgRef
}
return i.imgRef, nil
}
// sizer knows its size.
@ -507,6 +530,44 @@ func (i *Image) Dangling() bool {
// Labels returns the image's labels
func (i *Image) Labels() (map[string]string, error) {
imgInspect, err := i.imageInspectInfo()
if err != nil {
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
@ -519,7 +580,64 @@ func (i *Image) Labels() (map[string]string, error) {
if err != nil {
return nil, err
}
return imgInspect.Labels, nil
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

View File

@ -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
}

View File

@ -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
}