diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal.go | 2 | ||||
-rw-r--r-- | libpod/image/image.go | 178 | ||||
-rw-r--r-- | libpod/image_inspect.go | 89 | ||||
-rw-r--r-- | libpod/runtime_img.go | 6 |
4 files changed, 152 insertions, 123 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index c3cae8509..e228dd651 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -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 } diff --git a/libpod/image/image.go b/libpod/image/image.go index 15fc5174c..633a682cc 100644 --- a/libpod/image/image.go +++ b/libpod/image/image.go @@ -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()) - } - imgRef, err := ref.NewImage(nil) - if err != nil { - return nil, errors.Wrapf(err, "error reading 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 } - return imgRef, nil + return i.imgRef, nil } // sizer knows its size. @@ -507,19 +530,114 @@ 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, 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 } - ic, err := sr.NewImage(&types.SystemContext{}) + 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 } - imgInspect, err := ic.Inspect() + info, err := i.imageInspectInfo() if err != nil { return nil, err } - return imgInspect.Labels, nil + 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 diff --git a/libpod/image_inspect.go b/libpod/image_inspect.go deleted file mode 100644 index bedad3668..000000000 --- a/libpod/image_inspect.go +++ /dev/null @@ -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 -} diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index e3cb4e2c3..248d1c0aa 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -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 } |