aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-03-15 10:06:49 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-03-20 16:20:12 +0000
commit38a1b2f16d210525eafcc845e7a9cce598207113 (patch)
tree5616a12d68ebe55138fbde85f936a6bc90d4c8fd /libpod
parentecfa321288f10b70a59166f93296c77d262317fc (diff)
downloadpodman-38a1b2f16d210525eafcc845e7a9cce598207113.tar.gz
podman-38a1b2f16d210525eafcc845e7a9cce598207113.tar.bz2
podman-38a1b2f16d210525eafcc845e7a9cce598207113.zip
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
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container_api.go8
-rw-r--r--libpod/container_internal.go6
-rw-r--r--libpod/image/image.go130
-rw-r--r--libpod/image/image_test.go4
-rw-r--r--libpod/image/pull.go4
-rw-r--r--libpod/image/utils.go18
-rw-r--r--libpod/image_inspect.go26
-rw-r--r--libpod/runtime.go21
-rw-r--r--libpod/runtime_img.go202
9 files changed, 228 insertions, 191 deletions
diff --git a/libpod/container_api.go b/libpod/container_api.go
index ef94aa4c9..27c7994f4 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 2ee2174db..c3cae8509 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 b218c7d67..5e69a0a98 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 0e2f0c241..d9e8987a6 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 52ef175d4..8c43c6054 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 adc795e3a..76ec349f9 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 df2d3640e..bedad3668 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 cd519b3ab..5c3705ee9 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 fe9864dca..a58626855 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