From 38a1b2f16d210525eafcc845e7a9cce598207113 Mon Sep 17 00:00:00 2001
From: baude <bbaude@redhat.com>
Date: Thu, 15 Mar 2018 10:06:49 -0500
Subject: [PATCH] Image library stage 4 - create and commit

Migrate the podman create and commit subcommandis to leverage the images library.  I also had
to migrate the cmd/ portions of run and rmi.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #498
Approved by: mheon
---
 cmd/podman/commit.go         |  20 ++--
 cmd/podman/create.go         |  61 +++--------
 cmd/podman/history.go        |  11 +-
 cmd/podman/import.go         |  22 ++--
 cmd/podman/inspect.go        |  16 ++-
 cmd/podman/rmi.go            |  28 +++--
 cmd/podman/run.go            |   9 +-
 libpod/container_api.go      |   8 +-
 libpod/container_internal.go |   6 +-
 libpod/image/image.go        | 132 ++++++++++++++++++++---
 libpod/image/image_test.go   |   4 +-
 libpod/image/pull.go         |   4 +-
 libpod/image/utils.go        |  18 ++--
 libpod/image_inspect.go      |  26 +++--
 libpod/runtime.go            |  21 +++-
 libpod/runtime_img.go        | 202 +++++++++--------------------------
 test/e2e/pull_test.go        |   2 +-
 17 files changed, 304 insertions(+), 286 deletions(-)

diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 59ced293fb..34a086004f 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -2,11 +2,12 @@ package main
 
 import (
 	"fmt"
+	"io"
 	"os"
 
 	"github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
-	"github.com/projectatomic/libpod/libpod"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/urfave/cli"
 )
 
@@ -58,8 +59,11 @@ func commitCmd(c *cli.Context) error {
 	}
 	defer runtime.Shutdown(false)
 
-	var opts libpod.CopyOptions
-	var container string
+	var (
+		container string
+		reference string
+		writer    io.Writer
+	)
 	args := c.Args()
 	switch len(args) {
 	case 0:
@@ -68,7 +72,7 @@ func commitCmd(c *cli.Context) error {
 		container = args[0]
 	case 2:
 		container = args[0]
-		opts.Reference = args[1]
+		reference = args[1]
 	default:
 		return errors.Errorf("too many arguments. Usage CONTAINER [REFERENCE]")
 	}
@@ -90,20 +94,18 @@ func commitCmd(c *cli.Context) error {
 		History: history,
 		Author:  c.String("author"),
 	}
-	opts.ImageConfig = config
-	opts.Writer = nil
 
 	if !c.Bool("quiet") {
-		opts.Writer = os.Stderr
+		writer = os.Stderr
 	}
 
 	ctr, err := runtime.LookupContainer(container)
 	if err != nil {
 		return errors.Wrapf(err, "error looking up container %q", container)
 	}
-	img, err := ctr.Commit(c.BoolT("pause"), opts)
+	newImage, err := ctr.Commit(c.BoolT("pause"), reference, writer, image.SigningOptions{}, config)
 	if err == nil {
-		fmt.Println(img.ID)
+		fmt.Println(newImage.ID())
 	}
 	return nil
 }
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index efd7458ea9..947f6d2a60 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -3,13 +3,6 @@ package main
 import (
 	"encoding/json"
 	"fmt"
-	"io"
-	"net"
-	"os"
-	"strconv"
-	"strings"
-	"syscall"
-
 	"github.com/docker/docker/api/types/container"
 	"github.com/docker/docker/pkg/signal"
 	"github.com/docker/go-connections/nat"
@@ -17,10 +10,16 @@ import (
 	"github.com/opencontainers/selinux/go-selinux/label"
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/projectatomic/libpod/pkg/inspect"
 	"github.com/projectatomic/libpod/pkg/util"
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli"
+	"net"
+	"os"
+	"strconv"
+	"strings"
+	"syscall"
 )
 
 type mountType string
@@ -154,6 +153,7 @@ var createCommand = cli.Command{
 func createCmd(c *cli.Context) error {
 	// TODO should allow user to create based off a directory on the host not just image
 	// Need CLI support for this
+
 	if err := validateFlags(c, createFlags); err != nil {
 		return err
 	}
@@ -174,11 +174,14 @@ func createCmd(c *cli.Context) error {
 	}
 	defer runtime.Shutdown(false)
 
-	imageName, _, data, err := imageData(c, runtime, c.Args()[0])
+	rtc := runtime.GetConfig()
+
+	newImage, err := runtime.ImageRuntime().New(c.Args()[0], rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{})
 	if err != nil {
 		return err
 	}
-	createConfig, err := parseCreateOpts(c, runtime, imageName, data)
+	data, err := libpod.GetImageData(newImage)
+	createConfig, err := parseCreateOpts(c, runtime, newImage.Names()[0], data)
 	if err != nil {
 		return err
 	}
@@ -379,46 +382,6 @@ func exposedPorts(c *cli.Context, imageExposedPorts map[string]struct{}) (map[na
 	return portBindings, nil
 }
 
-// imageData pulls down the image if not stored locally and extracts the
-// default container runtime data out of it. imageData returns the data
-// to the caller.  Example Data: Entrypoint, Env, WorkingDir, Labels ...
-func imageData(c *cli.Context, runtime *libpod.Runtime, image string) (string, string, *inspect.ImageData, error) {
-	var (
-		err                error
-		imageName, imageID string
-	)
-	// Deal with the image after all the args have been checked
-	createImage := runtime.NewImage(image)
-	imageName, imageID, _ = createImage.GetLocalImageName()
-	if createImage.LocalName == "" {
-		// The image wasnt found by the user input'd name or its fqname
-		// Pull the image
-		var writer io.Writer
-		if !c.Bool("quiet") {
-			writer = os.Stderr
-		}
-		createImage.Pull(writer)
-	}
-
-	createImage.LocalName = imageName
-	if imageName == "" {
-		imageName, err = createImage.GetFQName()
-		_, imageID, _ = createImage.GetLocalImageName()
-	}
-	if err != nil {
-		return "", "", nil, err
-	}
-	storageImage, err := runtime.GetImage(imageName)
-	if err != nil {
-		return "", "", nil, errors.Wrapf(err, "error getting storage image %q", image)
-	}
-	data, err := runtime.GetImageInspectInfo(*storageImage)
-	if err != nil {
-		return "", "", nil, errors.Wrapf(err, "error parsing image data %q", image)
-	}
-	return imageName, imageID, data, err
-}
-
 // Parses CLI options related to container creation into a config which can be
 // parsed into an OCI runtime spec
 func parseCreateOpts(c *cli.Context, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*createConfig, error) {
diff --git a/cmd/podman/history.go b/cmd/podman/history.go
index 1164555d3e..0f9698f4f5 100644
--- a/cmd/podman/history.go
+++ b/cmd/podman/history.go
@@ -98,8 +98,11 @@ func historyCmd(c *cli.Context) error {
 	if len(args) > 1 {
 		return errors.Errorf("podman history takes at most 1 argument")
 	}
-	imgName := args[0]
 
+	image, err := runtime.ImageRuntime().NewFromLocal(args[0])
+	if err != nil {
+		return err
+	}
 	opts := historyOptions{
 		human:   c.BoolT("human"),
 		noTrunc: c.Bool("no-trunc"),
@@ -107,12 +110,12 @@ func historyCmd(c *cli.Context) error {
 		format:  format,
 	}
 
-	history, layers, imageID, err := runtime.GetHistory(imgName)
+	history, layers, err := image.History()
 	if err != nil {
-		return errors.Wrapf(err, "error getting history of image %q", imgName)
+		return errors.Wrapf(err, "error getting history of image %q", image.InputName)
 	}
 
-	return generateHistoryOutput(history, layers, imageID, opts)
+	return generateHistoryOutput(history, layers, image.ID(), opts)
 }
 
 func genHistoryFormat(format string, quiet bool) string {
diff --git a/cmd/podman/import.go b/cmd/podman/import.go
index d3c497d9df..6f7565b4b4 100644
--- a/cmd/podman/import.go
+++ b/cmd/podman/import.go
@@ -11,7 +11,7 @@ import (
 
 	"github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
-	"github.com/projectatomic/libpod/libpod"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/urfave/cli"
 )
 
@@ -55,8 +55,12 @@ func importCmd(c *cli.Context) error {
 	}
 	defer runtime.Shutdown(false)
 
-	var opts libpod.CopyOptions
-	var source string
+	var (
+		source    string
+		reference string
+		writer    io.Writer
+	)
+
 	args := c.Args()
 	switch len(args) {
 	case 0:
@@ -65,7 +69,7 @@ func importCmd(c *cli.Context) error {
 		source = args[0]
 	case 2:
 		source = args[0]
-		opts.Reference = args[1]
+		reference = args[1]
 	default:
 		return errors.Errorf("too many arguments. Usage TARBALL [REFERENCE]")
 	}
@@ -87,11 +91,9 @@ func importCmd(c *cli.Context) error {
 		History: history,
 	}
 
-	opts.ImageConfig = config
-	opts.Writer = nil
-
+	writer = nil
 	if !c.Bool("quiet") {
-		opts.Writer = os.Stderr
+		writer = os.Stderr
 	}
 
 	// if source is a url, download it and save to a temp file
@@ -105,9 +107,9 @@ func importCmd(c *cli.Context) error {
 		source = file
 	}
 
-	img, err := runtime.ImportImage(source, opts)
+	newImage, err := runtime.Import(source, reference, writer, image.SigningOptions{}, config)
 	if err == nil {
-		fmt.Println(img.ID)
+		fmt.Println(newImage.ID())
 	}
 	return err
 }
diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go
index cfd257af44..b691b7a122 100644
--- a/cmd/podman/inspect.go
+++ b/cmd/podman/inspect.go
@@ -128,31 +128,27 @@ func iterateInput(c *cli.Context, args []string, runtime *libpod.Runtime, inspec
 				break
 			}
 		case inspectTypeImage:
-			newImage := runtime.NewImage(input)
-			newImage.GetLocalImageName()
-			image, err := runtime.GetImage(newImage.LocalName)
+			image, err := runtime.ImageRuntime().NewFromLocal(input)
 			if err != nil {
 				inspectError = errors.Wrapf(err, "error getting image %q", input)
 				break
 			}
-			data, err = runtime.GetImageInspectInfo(*image)
+			data, err = libpod.GetImageData(image)
 			if err != nil {
-				inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID)
+				inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
 				break
 			}
 		case inspectAll:
 			ctr, err := runtime.LookupContainer(input)
 			if err != nil {
-				newImage := runtime.NewImage(input)
-				newImage.GetLocalImageName()
-				image, err := runtime.GetImage(newImage.LocalName)
+				image, err := runtime.ImageRuntime().NewFromLocal(input)
 				if err != nil {
 					inspectError = errors.Wrapf(err, "error getting image %q", input)
 					break
 				}
-				data, err = runtime.GetImageInspectInfo(*image)
+				data, err = libpod.GetImageData(image)
 				if err != nil {
-					inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID)
+					inspectError = errors.Wrapf(err, "error parsing image data %q", image.ID())
 					break
 				}
 			} else {
diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go
index f5938ffb98..b38686a87f 100644
--- a/cmd/podman/rmi.go
+++ b/cmd/podman/rmi.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/urfave/cli"
 )
 
@@ -51,28 +52,37 @@ func rmiCmd(c *cli.Context) error {
 		return errors.Errorf("when using the --all switch, you may not pass any images names or IDs")
 	}
 
-	imagesToDelete := args[:]
+	images := args[:]
 	var lastError error
+	var imagesToDelete []*image.Image
 	if removeAll {
-		localImages, err := runtime.GetImages(&libpod.ImageFilterParams{})
+		imagesToDelete, err = runtime.GetImages(&libpod.ImageFilterParams{})
 		if err != nil {
 			return errors.Wrapf(err, "unable to query local images")
 		}
-		for _, image := range localImages {
-			imagesToDelete = append(imagesToDelete, image.ID)
+	} else {
+		// Create image.image objects for deletion from user input
+		for _, i := range images {
+			newImage, err := runtime.ImageRuntime().NewFromLocal(i)
+			if err != nil {
+				fmt.Fprintln(os.Stderr, err)
+				continue
+			}
+			imagesToDelete = append(imagesToDelete, newImage)
 		}
 	}
-
-	for _, arg := range imagesToDelete {
-		image := runtime.NewImage(arg)
-		iid, err := image.Remove(c.Bool("force"))
+	if len(imagesToDelete) == 0 {
+		return errors.Errorf("no valid images to delete")
+	}
+	for _, img := range imagesToDelete {
+		err := runtime.RemoveImage(img, c.Bool("force"))
 		if err != nil {
 			if lastError != nil {
 				fmt.Fprintln(os.Stderr, lastError)
 			}
 			lastError = err
 		} else {
-			fmt.Println(iid)
+			fmt.Println(img.ID())
 		}
 	}
 	return lastError
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index 7b840a3876..f1e11f839c 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -7,8 +7,10 @@ import (
 
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/sirupsen/logrus"
 	"github.com/urfave/cli"
+	"os"
 )
 
 var runDescription = "Runs a command in a new container from the given image"
@@ -49,12 +51,15 @@ func runCmd(c *cli.Context) error {
 		return errors.Errorf("image name or ID is required")
 	}
 
-	imageName, _, data, err := imageData(c, runtime, c.Args()[0])
+	rtc := runtime.GetConfig()
+	newImage, err := runtime.ImageRuntime().New(c.Args()[0], rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{})
+
+	data, err := libpod.GetImageData(newImage)
 	if err != nil {
 		return err
 	}
 
-	createConfig, err := parseCreateOpts(c, runtime, imageName, data)
+	createConfig, err := parseCreateOpts(c, runtime, newImage.Names()[0], data)
 	if err != nil {
 		return err
 	}
diff --git a/libpod/container_api.go b/libpod/container_api.go
index ef94aa4c92..27c7994f4d 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -1,16 +1,18 @@
 package libpod
 
 import (
+	"io"
 	"io/ioutil"
 	"os"
 	"strconv"
 	"time"
 
-	"github.com/containers/storage"
 	"github.com/docker/docker/daemon/caps"
 	"github.com/docker/docker/pkg/stringid"
+	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod/driver"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/projectatomic/libpod/pkg/inspect"
 	"github.com/sirupsen/logrus"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -532,7 +534,7 @@ func (c *Container) Inspect(size bool) (*inspect.ContainerInspectData, error) {
 
 // Commit commits the changes between a container and its image, creating a new
 // image
-func (c *Container) Commit(pause bool, options CopyOptions) (*storage.Image, error) {
+func (c *Container) Commit(pause bool, reference string, writer io.Writer, signingOptions image.SigningOptions, imageConfig ociv1.Image) (*image.Image, error) {
 	if !c.locked {
 		c.lock.Lock()
 		defer c.lock.Unlock()
@@ -563,7 +565,7 @@ func (c *Container) Commit(pause bool, options CopyOptions) (*storage.Image, err
 	if err := c.export(tempFile.Name()); err != nil {
 		return nil, err
 	}
-	return c.runtime.ImportImage(tempFile.Name(), options)
+	return image.Import(tempFile.Name(), reference, writer, signingOptions, imageConfig, c.runtime.imageRuntime)
 }
 
 // Wait blocks on a container to exit and returns its exit code
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 2ee2174db8..c3cae8509b 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -926,16 +926,14 @@ func (c *Container) addImageVolumes(g *generate.Generator) error {
 	if !c.state.Mounted {
 		return errors.Wrapf(ErrInternal, "container is not mounted")
 	}
-
-	imageStorage, err := c.runtime.getImage(c.config.RootfsImageID)
+	newImage, err := c.runtime.imageRuntime.NewFromLocal(c.config.RootfsImageID)
 	if err != nil {
 		return err
 	}
-	imageData, err := c.runtime.getImageInspectInfo(*imageStorage)
+	imageData, err := GetImageData(newImage)
 	if err != nil {
 		return err
 	}
-
 	for k := range imageData.ContainerConfig.Volumes {
 		mount := spec.Mount{
 			Destination: k,
diff --git a/libpod/image/image.go b/libpod/image/image.go
index b218c7d677..5e69a0a980 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -12,6 +12,7 @@ import (
 	cp "github.com/containers/image/copy"
 	"github.com/containers/image/docker/reference"
 	is "github.com/containers/image/storage"
+	"github.com/containers/image/tarball"
 	"github.com/containers/image/transports/alltransports"
 	"github.com/containers/image/types"
 	"github.com/containers/storage"
@@ -19,6 +20,8 @@ import (
 	"github.com/opencontainers/go-digest"
 	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
+	"github.com/projectatomic/libpod/libpod/common"
+	"github.com/projectatomic/libpod/libpod/driver"
 	"github.com/projectatomic/libpod/pkg/inspect"
 	"github.com/projectatomic/libpod/pkg/util"
 )
@@ -36,12 +39,20 @@ type Image struct {
 
 // Runtime contains the store
 type Runtime struct {
-	store storage.Store
+	store               storage.Store
+	SignaturePolicyPath string
 }
 
-// NewImageRuntime creates an Image Runtime including the store given
+// NewImageRuntimeFromStore creates an ImageRuntime based on a provided store
+func NewImageRuntimeFromStore(store storage.Store) *Runtime {
+	return &Runtime{
+		store: store,
+	}
+}
+
+// NewImageRuntimeFromOptions creates an Image Runtime including the store given
 // store options
-func NewImageRuntime(options storage.StoreOptions) (*Runtime, error) {
+func NewImageRuntimeFromOptions(options storage.StoreOptions) (*Runtime, error) {
 	if reexec.Init() {
 		return nil, errors.Errorf("unable to reexec")
 	}
@@ -110,10 +121,12 @@ func (ir *Runtime) New(name, signaturePolicyPath, authfile string, writer io.Wri
 	}
 
 	// The image is not local
-
+	if signaturePolicyPath == "" {
+		signaturePolicyPath = ir.SignaturePolicyPath
+	}
 	imageName, err := newImage.pullImage(writer, authfile, signaturePolicyPath, signingoptions, dockeroptions)
 	if err != nil {
-		return &newImage, errors.Errorf("unable to pull %s", name)
+		return nil, errors.Errorf("unable to pull %s", name)
 	}
 
 	newImage.InputName = imageName
@@ -141,7 +154,7 @@ func (i *Image) reloadImage() error {
 // getLocalImage resolves an unknown input describing an image and
 // returns a storage.Image or an error. It is used by NewFromLocal.
 func (i *Image) getLocalImage() (*storage.Image, error) {
-	imageError := fmt.Sprintf("unable to find '%s' in local storage\n", i.InputName)
+	imageError := fmt.Sprintf("unable to find '%s' in local storage", i.InputName)
 	if i.InputName == "" {
 		return nil, errors.Errorf("input name is blank")
 	}
@@ -187,8 +200,7 @@ func (i *Image) getLocalImage() (*storage.Image, error) {
 	if err == nil {
 		return repoImage, nil
 	}
-
-	return nil, errors.Errorf("%s", imageError)
+	return nil, errors.Wrapf(err, imageError)
 }
 
 // hasRegistry returns a bool/err response if the image has a registry in its
@@ -307,7 +319,11 @@ func (ir *Runtime) GetImages() ([]*Image, error) {
 		return nil, err
 	}
 	for _, i := range images {
-		newImages = append(newImages, ir.newFromStorage(&i))
+		// iterating over these, be careful to not iterate on the literal
+		// pointer.
+		image := i
+		img := ir.newFromStorage(&image)
+		newImages = append(newImages, img)
 	}
 	return newImages, nil
 }
@@ -338,10 +354,24 @@ func (i *Image) TagImage(tag string) error {
 	return i.imageruntime.store.SetNames(i.ID(), tags)
 }
 
+// UntagImage removes a tag from the given image
+func (i *Image) UntagImage(tag string) error {
+	var newTags []string
+	tags := i.Names()
+	if !util.StringInSlice(tag, tags) {
+		return nil
+	}
+	for _, t := range tags {
+		if tag != t {
+			newTags = append(newTags, t)
+		}
+	}
+	i.reloadImage()
+	return i.imageruntime.store.SetNames(i.ID(), newTags)
+}
+
 // PushImage pushes the given image to a location described by the given path
 func (i *Image) PushImage(destination, manifestMIMEType, authFile, signaturePolicyPath string, writer io.Writer, forceCompress bool, signingOptions SigningOptions, dockerRegistryOptions *DockerRegistryOptions) error {
-	// PushImage pushes the src image to the destination
-	//func PushImage(source, destination string, options CopyOptions) error {
 	if destination == "" {
 		return errors.Wrapf(syscall.EINVAL, "destination image name must be specified")
 	}
@@ -395,6 +425,12 @@ func (i *Image) toStorageReference() (types.ImageReference, error) {
 	return is.Transport.ParseStoreReference(i.imageruntime.store, i.ID())
 }
 
+// ToImageRef returns an image reference type from an image
+// TODO: Hopefully we can remove this exported function for mheon
+func (i *Image) ToImageRef() (types.Image, error) {
+	return i.toImageRef()
+}
+
 // 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())
@@ -431,5 +467,77 @@ func (i *Image) Size() (*uint64, error) {
 		}
 	}
 	return nil, errors.Errorf("unable to determine size")
-
+}
+
+// DriverData gets the driver data from the store on a layer
+func (i *Image) DriverData() (*inspect.Data, error) {
+	topLayer, err := i.Layer()
+	if err != nil {
+		return nil, err
+	}
+	return driver.GetDriverData(i.imageruntime.store, topLayer.ID)
+}
+
+// Layer returns the image's top layer
+func (i *Image) Layer() (*storage.Layer, error) {
+	return i.imageruntime.store.Layer(i.image.TopLayer)
+}
+
+// History gets the history of an image and information about its layers
+func (i *Image) History() ([]ociv1.History, []types.BlobInfo, error) {
+	img, err := i.toImageRef()
+	if err != nil {
+		return nil, nil, err
+	}
+	oci, err := img.OCIConfig()
+	if err != nil {
+		return nil, nil, err
+	}
+	return oci.History, img.LayerInfos(), 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
+	src, err := alltransports.ParseImageName(file)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error parsing image name %q", path)
+	}
+
+	updater, ok := src.(tarball.ConfigUpdater)
+	if !ok {
+		return nil, errors.Wrapf(err, "unexpected type, a tarball reference should implement tarball.ConfigUpdater")
+	}
+
+	annotations := make(map[string]string)
+
+	//	config imgspecv1.Image
+	err = updater.ConfigUpdate(imageConfig, annotations)
+	if err != nil {
+		return nil, errors.Wrapf(err, "error updating image config")
+	}
+
+	sc := common.GetSystemContext("", "", false)
+
+	// if reference not given, get the image digest
+	if reference == "" {
+		reference, err = getImageDigest(src, sc)
+		if err != nil {
+			return nil, err
+		}
+	}
+	policyContext, err := getPolicyContext(sc)
+	if err != nil {
+		return nil, err
+	}
+	defer policyContext.Destroy()
+	copyOptions := getCopyOptions(writer, "", nil, nil, signingOptions, "", "", false)
+	dest, err := is.Transport.ParseStoreReference(runtime.store, reference)
+	if err != nil {
+		errors.Wrapf(err, "error getting image reference for %q", reference)
+	}
+	if err = cp.Image(policyContext, dest, src, copyOptions); err != nil {
+		return nil, err
+	}
+	return runtime.NewFromLocal(reference)
 }
diff --git a/libpod/image/image_test.go b/libpod/image/image_test.go
index 0e2f0c2410..d9e8987a67 100644
--- a/libpod/image/image_test.go
+++ b/libpod/image/image_test.go
@@ -79,7 +79,7 @@ func TestImage_NewFromLocal(t *testing.T) {
 	writer = os.Stdout
 
 	// Need images to be present for this test
-	ir, err := NewImageRuntime(so)
+	ir, err := NewImageRuntimeFromOptions(so)
 	assert.NoError(t, err)
 	bb, err := ir.New("docker.io/library/busybox:latest", "", "", writer, nil, SigningOptions{})
 	assert.NoError(t, err)
@@ -115,7 +115,7 @@ func TestImage_New(t *testing.T) {
 		RunRoot:   workdir,
 		GraphRoot: workdir,
 	}
-	ir, err := NewImageRuntime(so)
+	ir, err := NewImageRuntimeFromOptions(so)
 	assert.NoError(t, err)
 	// Build the list of pull names
 	names = append(names, bbNames...)
diff --git a/libpod/image/pull.go b/libpod/image/pull.go
index 52ef175d49..8c43c60545 100644
--- a/libpod/image/pull.go
+++ b/libpod/image/pull.go
@@ -177,8 +177,8 @@ func (i *Image) pullImage(writer io.Writer, authfile, signaturePolicyPath string
 	copyOptions := getCopyOptions(writer, signaturePolicyPath, dockerOptions, nil, signingOptions, authfile, "", false)
 	for _, imageInfo := range pullStructs {
 		// Print the following statement only when pulling from a docker or atomic registry
-		if writer != nil && (imageInfo.srcRef.Transport().Name() == DockerTransport || imageInfo.srcRef.Transport().Name() == AtomicTransport) {
-			io.WriteString(writer, fmt.Sprintf("Trying to pull %s...\n", imageInfo.image))
+		if writer != nil && (strings.HasPrefix(DockerTransport, imageInfo.srcRef.Transport().Name()) || imageInfo.srcRef.Transport().Name() == AtomicTransport) {
+			io.WriteString(writer, fmt.Sprintf("Trying to pull %s...", imageInfo.image))
 		}
 		if err = cp.Image(policyContext, imageInfo.dstRef, imageInfo.srcRef, copyOptions); err != nil {
 			if writer != nil {
diff --git a/libpod/image/utils.go b/libpod/image/utils.go
index adc795e3ab..76ec349f95 100644
--- a/libpod/image/utils.go
+++ b/libpod/image/utils.go
@@ -2,15 +2,14 @@ package image
 
 import (
 	"io"
+	"strings"
 
 	cp "github.com/containers/image/copy"
 	"github.com/containers/image/docker/reference"
-	"github.com/containers/storage"
-	"github.com/pkg/errors"
-
 	"github.com/containers/image/signature"
 	"github.com/containers/image/types"
-	"strings"
+	"github.com/containers/storage"
+	"github.com/pkg/errors"
 )
 
 func getTags(nameInput string) (reference.NamedTagged, bool, error) {
@@ -36,14 +35,19 @@ func findImageInRepotags(search imageParts, images []*Image) (*storage.Image, er
 			}
 			if d.name == search.name && d.tag == search.tag {
 				results = append(results, image.image)
-				break
+				continue
+			}
+			// account for registry:/somedir/image
+			if strings.HasSuffix(d.name, search.name) && d.tag == search.tag {
+				results = append(results, image.image)
+				continue
 			}
 		}
 	}
 	if len(results) == 0 {
-		return &storage.Image{}, errors.Errorf("unable to find a name and tag match for %s in repotags", search)
+		return &storage.Image{}, errors.Errorf("unable to find a name and tag match for %s in repotags", search.name)
 	} else if len(results) > 1 {
-		return &storage.Image{}, errors.Errorf("found multiple name and tag matches for %s in repotags", search)
+		return &storage.Image{}, errors.Errorf("found multiple name and tag matches for %s in repotags", search.name)
 	}
 	return results[0], nil
 }
diff --git a/libpod/image_inspect.go b/libpod/image_inspect.go
index df2d3640e3..bedad36680 100644
--- a/libpod/image_inspect.go
+++ b/libpod/image_inspect.go
@@ -4,18 +4,22 @@ import (
 	"encoding/json"
 	"strings"
 
-	"github.com/containers/image/types"
-	"github.com/containers/storage"
 	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"
 )
 
-func getImageData(img storage.Image, imgRef types.Image, size int64, driver *inspect.Data) (*inspect.ImageData, error) {
-	imgSize, err := imgRef.Size()
+// GetImageData returns an image's inspect data
+func GetImageData(img *image.Image) (*inspect.ImageData, error) {
+	imgRef, err := img.ToImageRef()
 	if err != nil {
-		return nil, errors.Wrapf(err, "error reading size of image %q", img.ID)
+		return nil, err
+	}
+	size, err := imgRef.Size()
+	if err != nil {
+		return nil, err
 	}
 	manifest, manifestType, err := imgRef.Manifest()
 	if err != nil {
@@ -37,13 +41,17 @@ func getImageData(img storage.Image, imgRef types.Image, size int64, driver *ins
 	}
 
 	var repoDigests []string
-	for _, name := range img.Names {
+	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,
+		ID:              img.ID(),
+		RepoTags:        img.Names(),
 		RepoDigests:     repoDigests,
 		Comment:         ociv1Img.History[0].Comment,
 		Created:         ociv1Img.Created,
@@ -53,7 +61,7 @@ func getImageData(img storage.Image, imgRef types.Image, size int64, driver *ins
 		ContainerConfig: &ociv1Img.Config,
 		Version:         info.DockerVersion,
 		Size:            size,
-		VirtualSize:     size + imgSize,
+		VirtualSize:     size,
 		Annotations:     annotations,
 		Digest:          imgDigest,
 		Labels:          info.Labels,
diff --git a/libpod/runtime.go b/libpod/runtime.go
index cd519b3ab4..5c3705ee93 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -13,6 +13,7 @@ import (
 	"github.com/containers/storage"
 	"github.com/cri-o/ocicni/pkg/ocicni"
 	"github.com/pkg/errors"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/sirupsen/logrus"
 	"github.com/ulule/deepcopier"
 )
@@ -69,6 +70,7 @@ type Runtime struct {
 	conmonPath     string
 	valid          bool
 	lock           sync.RWMutex
+	imageRuntime   *image.Runtime
 }
 
 // RuntimeConfig contains configuration options used to set up the runtime
@@ -194,11 +196,9 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) {
 			return nil, errors.Wrapf(err, "error configuring runtime")
 		}
 	}
-
 	if err := makeRuntime(runtime); err != nil {
 		return nil, err
 	}
-
 	return runtime, nil
 }
 
@@ -293,8 +293,20 @@ func makeRuntime(runtime *Runtime) error {
 	if err != nil {
 		return err
 	}
+
 	runtime.store = store
 	is.Transport.SetStore(store)
+
+	// Set up image runtime and store in runtime
+	ir := image.NewImageRuntimeFromStore(runtime.store)
+	if err != nil {
+		return err
+	}
+
+	runtime.imageRuntime = ir
+
+	// Setting signaturepolicypath
+	ir.SignaturePolicyPath = runtime.config.SignaturePolicyPath
 	defer func() {
 		if err != nil {
 			// Don't forcibly shut down
@@ -576,3 +588,8 @@ func SaveDefaultConfig(path string) error {
 
 	return ioutil.WriteFile(path, w.Bytes(), 0644)
 }
+
+// ImageRuntime returns the imageruntime for image resolution
+func (r *Runtime) ImageRuntime() *image.Runtime {
+	return r.imageRuntime
+}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index fe9864dcad..a586268552 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -27,7 +27,7 @@ import (
 	ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
 	"github.com/pkg/errors"
 	"github.com/projectatomic/libpod/libpod/common"
-	"github.com/projectatomic/libpod/libpod/driver"
+	"github.com/projectatomic/libpod/libpod/image"
 	"github.com/projectatomic/libpod/pkg/inspect"
 	"github.com/projectatomic/libpod/pkg/util"
 )
@@ -152,7 +152,7 @@ func (r *Runtime) IsImageID(input string) (bool, error) {
 		return false, errors.Wrapf(err, "unable to get images")
 	}
 	for _, image := range images {
-		if strings.HasPrefix(image.ID, input) {
+		if strings.HasPrefix(image.ID(), input) {
 			return true, nil
 		}
 	}
@@ -167,8 +167,8 @@ func (k *Image) GetNameByID() (string, error) {
 		return "", errors.Wrapf(err, "unable to get images")
 	}
 	for _, image := range images {
-		if strings.HasPrefix(image.ID, k.Name) {
-			return image.Names[0], nil
+		if strings.HasPrefix(image.ID(), k.Name) {
+			return image.Names()[0], nil
 		}
 	}
 	return "", errors.Errorf("unable to determine image for %s", k.Name)
@@ -196,13 +196,13 @@ func (k *Image) GetImageID() (string, error) {
 	}
 	for _, image := range images {
 		// Check if we have an ID match
-		if strings.HasPrefix(image.ID, k.Name) {
-			return image.ID, nil
+		if strings.HasPrefix(image.ID(), k.Name) {
+			return image.ID(), nil
 		}
 		// Check if we have a name match, perhaps a tagged name
-		for _, name := range image.Names {
+		for _, name := range image.Names() {
 			if k.Name == name {
-				return image.ID, nil
+				return image.ID(), nil
 			}
 		}
 	}
@@ -364,7 +364,7 @@ func (k *Image) GetLocalImageName() (string, string, error) {
 		return "", "", err
 	}
 	for _, image := range localImages {
-		for _, name := range image.Names {
+		for _, name := range image.Names() {
 			imgRef, err := reference.Parse(name)
 			if err != nil {
 				continue
@@ -383,13 +383,13 @@ func (k *Image) GetLocalImageName() (string, string, error) {
 
 			if imageName == k.Name {
 				k.LocalName = name
-				return name, image.ID, nil
+				return name, image.ID(), nil
 			}
 			imageSplit := strings.Split(imageName, "/")
 			baseName := imageSplit[len(imageSplit)-1]
 			if baseName == k.Name {
 				k.LocalName = name
-				return name, image.ID, nil
+				return name, image.ID(), nil
 			}
 		}
 	}
@@ -431,26 +431,6 @@ func (k *Image) Pull(writer io.Writer) error {
 	return nil
 }
 
-// Remove calls into container storage and deletes the image
-func (k *Image) Remove(force bool) (string, error) {
-	if k.LocalName == "" {
-		// This populates the images local name
-		_, _, err := k.GetLocalImageName()
-		if err != nil {
-			return "", errors.Wrapf(err, "unable to find %s locally", k.Name)
-		}
-	}
-	iid, err := k.GetImageID()
-	if err != nil {
-		return "", errors.Wrapf(err, "unable to get image id")
-	}
-	image, err := k.runtime.GetImage(iid)
-	if err != nil {
-		return "", errors.Wrapf(err, "unable to remove %s", iid)
-	}
-	return k.runtime.RemoveImage(image, force)
-}
-
 // GetRegistries gets the searchable registries from the global registration file.
 func GetRegistries() ([]string, error) {
 	registryConfigPath := ""
@@ -497,7 +477,7 @@ func getRegistries() ([]string, error) {
 // ImageFilter is a function to determine whether an image is included in
 // command output. Images to be outputted are tested using the function. A true
 // return will include the image, a false return will exclude it.
-type ImageFilter func(*storage.Image, *inspect.ImageData) bool
+type ImageFilter func(*image.Image, *inspect.ImageData) bool
 
 func (ips imageDecomposeStruct) returnFQName() string {
 	return fmt.Sprintf("%s%s/%s:%s", ips.transport, ips.registry, ips.imageName, ips.tag)
@@ -854,50 +834,52 @@ func (r *Runtime) UntagImage(image *storage.Image, tag string) (string, error) {
 
 // RemoveImage deletes an image from local storage
 // Images being used by running containers can only be removed if force=true
-func (r *Runtime) RemoveImage(image *storage.Image, force bool) (string, error) {
+func (r *Runtime) RemoveImage(image *image.Image, force bool) error {
 	r.lock.Lock()
 	defer r.lock.Unlock()
 
 	if !r.valid {
-		return "", ErrRuntimeStopped
+		return ErrRuntimeStopped
 	}
 
 	// Get all containers, filter to only those using the image, and remove those containers
 	ctrs, err := r.state.AllContainers()
 	if err != nil {
-		return "", err
+		return err
 	}
 	imageCtrs := []*Container{}
 	for _, ctr := range ctrs {
-		if ctr.config.RootfsImageID == image.ID {
+		if ctr.config.RootfsImageID == image.ID() {
 			imageCtrs = append(imageCtrs, ctr)
 		}
 	}
-	if len(imageCtrs) > 0 && len(image.Names) <= 1 {
+	if len(imageCtrs) > 0 && len(image.Names()) <= 1 {
 		if force {
 			for _, ctr := range imageCtrs {
 				if err := r.removeContainer(ctr, true); err != nil {
-					return "", errors.Wrapf(err, "error removing image %s: container %s using image could not be removed", image.ID, ctr.ID())
+					return errors.Wrapf(err, "error removing image %s: container %s using image could not be removed", image.ID, ctr.ID())
 				}
 			}
 		} else {
-			return "", fmt.Errorf("could not remove image %s as it is being used by %d containers", image.ID, len(imageCtrs))
+			return fmt.Errorf("could not remove image %s as it is being used by %d containers", image.ID, len(imageCtrs))
 		}
 	}
 
-	if len(image.Names) > 1 && !force {
-		return "", fmt.Errorf("unable to delete %s (must force) - image is referred to in multiple tags", image.ID)
+	if len(image.Names()) > 1 && !force {
+		return fmt.Errorf("unable to delete %s (must force) - image is referred to in multiple tags", image.ID)
 	}
 
-	// If it is forced, we have to untag the image so that it can be deleted
-	if err = r.store.SetNames(image.ID, image.Names[:0]); err != nil {
-		return "", err
+	if len(image.Names()) > 1 && force {
+		// If it is forced, we have to untag the image so that it can be deleted
+		if err = r.store.SetNames(image.ID(), image.Names()[:0]); err != nil {
+			return err
+		}
 	}
-	_, err = r.store.DeleteImage(image.ID, true)
-	if err != nil {
-		return "", err
+
+	if err = image.Remove(force); err != nil {
+		return err
 	}
-	return image.ID, nil
+	return nil
 }
 
 // GetImage retrieves an image matching the given name or hash from system
@@ -964,7 +946,7 @@ func (r *Runtime) getImageRef(image string) (types.Image, error) {
 // Filters can be provided which will determine which images are included in the
 // output. Multiple filters are handled by ANDing their output, so only images
 // matching all filters are included
-func (r *Runtime) GetImages(params *ImageFilterParams, filters ...ImageFilter) ([]*storage.Image, error) {
+func (r *Runtime) GetImages(params *ImageFilterParams, filters ...ImageFilter) ([]*image.Image, error) {
 	r.lock.RLock()
 	defer r.lock.RUnlock()
 
@@ -972,21 +954,21 @@ func (r *Runtime) GetImages(params *ImageFilterParams, filters ...ImageFilter) (
 		return nil, ErrRuntimeStopped
 	}
 
-	images, err := r.store.Images()
+	images, err := r.imageRuntime.GetImages()
 	if err != nil {
 		return nil, err
 	}
-
-	var imagesFiltered []*storage.Image
+	var imagesFiltered []*image.Image
 
 	for _, img := range images {
-		info, err := r.getImageInspectInfo(img)
+		info, err := GetImageData(img)
+
 		if err != nil {
 			return nil, err
 		}
 		var names []string
-		if len(img.Names) > 0 {
-			names = img.Names
+		if len(img.Names()) > 0 {
+			names = img.Names()
 		} else {
 			names = append(names, "<none>")
 		}
@@ -996,13 +978,14 @@ func (r *Runtime) GetImages(params *ImageFilterParams, filters ...ImageFilter) (
 				params.ImageName = name
 			}
 			for _, filter := range filters {
-				include = include && filter(&img, info)
+				include = include && filter(img, info)
 			}
 
 			if include {
 				newImage := img
-				newImage.Names = []string{name}
-				imagesFiltered = append(imagesFiltered, &newImage)
+				// TODO I dont think this is needed.  Will verify along the way
+				//newImage.Names = []string{name}
+				imagesFiltered = append(imagesFiltered, newImage)
 			}
 		}
 	}
@@ -1037,92 +1020,9 @@ func (r *Runtime) GetHistory(image string) ([]ociv1.History, []types.BlobInfo, s
 	return oci.History, src.LayerInfos(), img.ID, nil
 }
 
-// ImportImage imports an OCI format image archive into storage as an image
-func (r *Runtime) ImportImage(path string, options CopyOptions) (*storage.Image, error) {
-	r.lock.RLock()
-	defer r.lock.RUnlock()
-
-	if !r.valid {
-		return nil, ErrRuntimeStopped
-	}
-
-	file := TarballTransport + ":" + path
-	src, err := alltransports.ParseImageName(file)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error parsing image name %q", path)
-	}
-
-	updater, ok := src.(tarball.ConfigUpdater)
-	if !ok {
-		return nil, errors.Wrapf(err, "unexpected type, a tarball reference should implement tarball.ConfigUpdater")
-	}
-
-	annotations := make(map[string]string)
-
-	err = updater.ConfigUpdate(options.ImageConfig, annotations)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error updating image config")
-	}
-
-	var reference = options.Reference
-	sc := common.GetSystemContext("", "", false)
-
-	// if reference not given, get the image digest
-	if reference == "" {
-		reference, err = getImageDigest(src, sc)
-		if err != nil {
-			return nil, err
-		}
-	}
-
-	policyContext, err := getPolicyContext(sc)
-	if err != nil {
-		return nil, err
-	}
-	defer policyContext.Destroy()
-	copyOptions := common.GetCopyOptions(options.Writer, "", nil, nil, common.SigningOptions{}, "", "", false)
-
-	dest, err := is.Transport.ParseStoreReference(r.store, reference)
-	if err != nil {
-		errors.Wrapf(err, "error getting image reference for %q", options.Reference)
-	}
-	if err = cp.Image(policyContext, dest, src, copyOptions); err != nil {
-		return nil, err
-	}
-	// Use no lock version of GetImage
-	return r.getImage(reference)
-}
-
-// GetImageInspectInfo returns the inspect information of an image
-func (r *Runtime) GetImageInspectInfo(image storage.Image) (*inspect.ImageData, error) {
-	r.lock.RLock()
-	defer r.lock.RUnlock()
-
-	if !r.valid {
-		return nil, ErrRuntimeStopped
-	}
-	return r.getImageInspectInfo(image)
-}
-
-func (r *Runtime) getImageInspectInfo(image storage.Image) (*inspect.ImageData, error) {
-	imgRef, err := r.getImageRef("@" + image.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading image %q", image.ID)
-	}
-
-	layer, err := r.store.Layer(image.TopLayer)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error reading information about layer %q", image.TopLayer)
-	}
-	size, err := r.store.DiffSize(layer.Parent, layer.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error determining size of layer %q", layer.ID)
-	}
-	driverData, err := driver.GetDriverData(r.store, layer.ID)
-	if err != nil {
-		return nil, errors.Wrapf(err, "error getting graph driver info %q", image.ID)
-	}
-	return getImageData(image, imgRef, size, driverData)
+//Import imports an oci format image archive into storage as an image
+func (r *Runtime) Import(path, reference string, writer io.Writer, signingOptions image.SigningOptions, imageConfig ociv1.Image) (*image.Image, error) {
+	return image.Import(path, reference, writer, signingOptions, imageConfig, r.imageRuntime)
 }
 
 // ParseImageFilter takes a set of images and a filter string as input, and returns the libpod.ImageFilterParams struct
@@ -1145,7 +1045,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
 		return &params, nil
 	}
 
-	images, err := r.store.Images()
+	images, err := r.imageRuntime.GetImages()
 	if err != nil {
 		return nil, err
 	}
@@ -1164,7 +1064,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 := r.GetImageInspectInfo(img)
+				info, err := GetImageData(img)
 				if err != nil {
 					return nil, err
 				}
@@ -1174,7 +1074,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
 			}
 		case "since":
 			if img, err := findImageInSlice(images, pair[1]); err == nil {
-				info, err := r.GetImageInspectInfo(img)
+				info, err := GetImageData(img)
 				if err != nil {
 					return nil, err
 				}
@@ -1240,18 +1140,18 @@ func ParseImageNames(names []string) (tags, digests []string, err error) {
 	return tags, digests, nil
 }
 
-func findImageInSlice(images []storage.Image, ref string) (storage.Image, error) {
+func findImageInSlice(images []*image.Image, ref string) (*image.Image, error) {
 	for _, image := range images {
-		if MatchesID(image.ID, ref) {
+		if MatchesID(image.ID(), ref) {
 			return image, nil
 		}
-		for _, name := range image.Names {
+		for _, name := range image.Names() {
 			if MatchesReference(name, ref) {
 				return image, nil
 			}
 		}
 	}
-	return storage.Image{}, errors.New("could not find image")
+	return nil, errors.New("could not find image")
 }
 
 // getImageDigest creates an image object and uses the hex value of the digest as the image ID
diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go
index 25e33240ea..bb2d0c3a0b 100644
--- a/test/e2e/pull_test.go
+++ b/test/e2e/pull_test.go
@@ -140,7 +140,7 @@ var _ = Describe("Podman pull", func() {
 		clean.WaitWithDefaultTimeout()
 	})
 
-	It("podman pull from local directory", func() {
+	It("podman pull check quiet", func() {
 		podmanTest.RestoreArtifact(ALPINE)
 		setup := podmanTest.Podman([]string{"images", ALPINE, "-q", "--no-trunc"})
 		setup.WaitWithDefaultTimeout()