Move libkpod/image libkpod/layer to libpod/images and libpod/layers

Begin moving image and layer handling out of libkpod into libpod.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh 2017-08-31 11:17:21 -04:00
parent 47ef2f66df
commit e18e962238
26 changed files with 272 additions and 104 deletions

View file

@ -12,7 +12,7 @@ import (
"github.com/containers/storage"
units "github.com/docker/go-units"
"github.com/kubernetes-incubator/cri-o/cmd/kpod/formats"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/common"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"

View file

@ -6,7 +6,7 @@ import (
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/cmd/kpod/formats"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
libpod "github.com/kubernetes-incubator/cri-o/libpod/images"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/urfave/cli"
@ -89,9 +89,9 @@ func imagesCmd(c *cli.Context) error {
return errors.New("'kpod images' requires at most 1 argument")
}
var params *libkpodimage.FilterParams
var params *libpod.FilterParams
if c.IsSet("filter") {
params, err = libkpodimage.ParseFilter(store, c.String("filter"))
params, err = libpod.ParseFilter(store, c.String("filter"))
if err != nil {
return errors.Wrapf(err, "error parsing filter")
}
@ -99,7 +99,7 @@ func imagesCmd(c *cli.Context) error {
params = nil
}
imageList, err := libkpodimage.GetImagesMatchingFilter(store, params, name)
imageList, err := libpod.GetImagesMatchingFilter(store, params, name)
if err != nil {
return errors.Wrapf(err, "could not get list of images matching filter")
}
@ -141,7 +141,7 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests
names = img.Names
}
info, imageDigest, size, _ := libkpodimage.InfoAndDigestAndSize(store, img)
info, imageDigest, size, _ := libpod.InfoAndDigestAndSize(store, img)
if info != nil {
createdTime = info.Created
}
@ -151,7 +151,7 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests
Name: names,
Digest: imageDigest,
CreatedAt: createdTime.Format("Jan 2, 2006 15:04"),
Size: libkpodimage.FormattedSize(float64(size)),
Size: libpod.FormattedSize(float64(size)),
}
imageOutput = append(imageOutput, params)
}

View file

@ -3,7 +3,7 @@ package main
import (
"github.com/kubernetes-incubator/cri-o/cmd/kpod/formats"
"github.com/kubernetes-incubator/cri-o/libkpod"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
@ -85,14 +85,14 @@ func inspectCmd(c *cli.Context) error {
return errors.Wrapf(err, "error parsing container data")
}
case inspectTypeImage:
data, err = libkpodimage.GetData(server.Store(), name)
data, err = images.GetData(server.Store(), name)
if err != nil {
return errors.Wrapf(err, "error parsing image data")
}
case inspectAll:
ctrData, err := server.GetContainerData(name, size)
if err != nil {
imgData, err := libkpodimage.GetData(server.Store(), name)
imgData, err := images.GetData(server.Store(), name)
if err != nil {
return errors.Wrapf(err, "error parsing container or image data")
}

View file

@ -7,8 +7,8 @@ import (
"io/ioutil"
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
@ -105,5 +105,5 @@ func loadImage(store storage.Store, opts loadOptions) error {
src := dockerArchive + opts.input
return libkpodimage.PullImage(store, src, false, opts.quiet, systemContext)
return images.PullImage(store, src, false, opts.quiet, systemContext)
}

View file

@ -2,7 +2,7 @@ package main
import (
"github.com/kubernetes-incubator/cri-o/libkpod/common"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
@ -58,7 +58,7 @@ func pullCmd(c *cli.Context) error {
systemContext := common.GetSystemContext("")
err = libkpodimage.PullImage(store, image, allTags, false, systemContext)
err = images.PullImage(store, image, allTags, false, systemContext)
if err != nil {
return errors.Errorf("error pulling image from %q: %v", image, err)
}

View file

@ -7,7 +7,7 @@ import (
"github.com/containers/image/types"
"github.com/containers/storage/pkg/archive"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal"
@ -120,5 +120,5 @@ func pushCmd(c *cli.Context) error {
if !c.Bool("quiet") {
options.ReportWriter = os.Stderr
}
return libkpodimage.PushImage(srcName, destName, options)
return images.PushImage(srcName, destName, options)
}

View file

@ -4,7 +4,7 @@ import (
"fmt"
"github.com/containers/storage"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
@ -49,7 +49,7 @@ func rmiCmd(c *cli.Context) error {
}
for _, id := range args {
image, err := libkpodimage.FindImage(store, id)
image, err := images.FindImage(store, id)
if err != nil {
return errors.Wrapf(err, "could not get image %q", id)
}
@ -68,14 +68,14 @@ func rmiCmd(c *cli.Context) error {
}
}
// If the user supplied an ID, we cannot delete the image if it is referred to by multiple tags
if libkpodimage.MatchesID(image.ID, id) {
if images.MatchesID(image.ID, 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
image.Names = image.Names[:0]
} else {
name, err2 := libkpodimage.UntagImage(store, image, id)
name, err2 := images.UntagImage(store, image, id)
if err2 != nil {
return err
}
@ -85,7 +85,7 @@ func rmiCmd(c *cli.Context) error {
if len(image.Names) > 0 {
continue
}
id, err := libkpodimage.RemoveImage(image, store)
id, err := images.RemoveImage(image, store)
if err != nil {
return err
}

View file

@ -4,7 +4,7 @@ import (
"os"
"github.com/containers/storage"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
@ -83,7 +83,7 @@ func saveCmd(c *cli.Context) error {
func saveImage(store storage.Store, opts saveOptions) error {
dst := dockerArchive + opts.output
pushOpts := libkpodimage.CopyOptions{
pushOpts := images.CopyOptions{
SignaturePolicyPath: "",
Store: store,
}
@ -92,7 +92,7 @@ func saveImage(store storage.Store, opts saveOptions) error {
// future pull requests will fix this
for _, image := range opts.images {
dest := dst + ":" + image
if err := libkpodimage.PushImage(image, dest, pushOpts); err != nil {
if err := images.PushImage(image, dest, pushOpts); err != nil {
return errors.Wrapf(err, "unable to save %q", image)
}
}

View file

@ -10,7 +10,7 @@ import (
tm "github.com/buger/goterm"
"github.com/kubernetes-incubator/cri-o/libkpod"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/pkg/errors"
"github.com/urfave/cli"
@ -179,7 +179,7 @@ func outputStatsUsingFormatString(stats *libkpod.ContainerStats) {
}
func combineHumanValues(a, b uint64) string {
return fmt.Sprintf("%s / %s", libkpodimage.FormattedSize(float64(a)), libkpodimage.FormattedSize(float64(b)))
return fmt.Sprintf("%s / %s", images.FormattedSize(float64(a)), images.FormattedSize(float64(b)))
}
func floatToPercentString(f float64) string {

View file

@ -3,7 +3,7 @@ package main
import (
"github.com/containers/image/docker/reference"
"github.com/containers/storage"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
@ -32,7 +32,7 @@ func tagCmd(c *cli.Context) error {
if err != nil {
return err
}
img, err := libkpodimage.FindImage(store, args[0])
img, err := images.FindImage(store, args[0])
if err != nil {
return err
}

View file

@ -7,8 +7,8 @@ import (
"k8s.io/apimachinery/pkg/fields"
pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
"github.com/kubernetes-incubator/cri-o/libkpod/driver"
libkpodimage "github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libpod/driver"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/opencontainers/image-spec/specs-go/v1"
specs "github.com/opencontainers/runtime-spec/specs-go"
@ -77,7 +77,7 @@ func (c *ContainerServer) GetContainerData(name string, size bool) (*ContainerDa
if container.ImageID == "" {
return nil, errors.Errorf("error reading container image data: container is not based on an image")
}
imageData, err := libkpodimage.GetData(c.store, container.ImageID)
imageData, err := images.GetData(c.store, container.ImageID)
if err != nil {
return nil, errors.Wrapf(err, "error reading container image data")
}

View file

@ -2,8 +2,8 @@ package libkpod
import (
"github.com/containers/storage/pkg/archive"
"github.com/kubernetes-incubator/cri-o/libkpod/image"
"github.com/kubernetes-incubator/cri-o/libkpod/layer"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/kubernetes-incubator/cri-o/libpod/layers"
"github.com/pkg/errors"
)
@ -28,11 +28,11 @@ func (c *ContainerServer) GetDiff(from, to string) ([]archive.Change, error) {
// If the id matches a layer, the top layer id is returned
func (c *ContainerServer) getLayerID(id string) (string, error) {
var toLayer string
toImage, err := image.FindImage(c.store, id)
toImage, err := images.FindImage(c.store, id)
if err != nil {
toCtr, err := c.store.Container(id)
if err != nil {
toLayer, err = layer.FullID(c.store, id)
toLayer, err = layers.FullID(c.store, id)
if err != nil {
return "", errors.Errorf("layer, image, or container %s does not exist", id)
}

223
libpod/image.go Normal file
View file

@ -0,0 +1,223 @@
package libpod
import (
"io"
"strings"
"syscall"
cp "github.com/containers/image/copy"
"github.com/containers/image/docker/tarfile"
"github.com/containers/image/manifest"
"github.com/containers/image/signature"
is "github.com/containers/image/storage"
"github.com/containers/image/transports/alltransports"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
"github.com/kubernetes-incubator/cri-o/libpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/ctr"
"github.com/kubernetes-incubator/cri-o/libpod/images"
"github.com/pkg/errors"
)
// Runtime API
const (
// DefaultRegistry is a prefix that we apply to an image name
// to check docker hub first for the image
DefaultRegistry = "docker://"
)
// CopyOptions contains the options given when pushing or pulling images
type CopyOptions struct {
// Compression specifies the type of compression which is applied to
// layer blobs. The default is to not use compression, but
// archive.Gzip is recommended.
Compression archive.Compression
// ReportWriter is an io.Writer which will be used to log the writing
// of the new image.
ReportWriter io.Writer
// Store is the local storage store which holds the source image.
Store storage.Store
// DockerRegistryOptions encapsulates settings that affect how we
// connect or authenticate to a remote registry to which we want to
// push the image.
common.DockerRegistryOptions
// SigningOptions encapsulates settings that control whether or not we
// strip or add signatures to the image when pushing (uploading) the
// image to a registry.
common.SigningOptions
}
// Image API
// 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) bool
// PullImage pulls an image from configured registries
// By default, only the latest tag (or a specific tag if requested) will be
// pulled. If allTags is true, all tags for the requested image will be pulled.
// Signature validation will be performed if the Runtime has been appropriately
// configured
func (r *Runtime) PullImage(imgName string, allTags bool) error {
// PullImage copies the image from the source to the destination
var (
images []string
)
srcRef, err := alltransports.ParseImageName(imgName)
if err != nil {
defaultName := DefaultRegistry + imgName
srcRef2, err2 := alltransports.ParseImageName(defaultName)
if err2 != nil {
return errors.Errorf("error parsing image name %q: %v", defaultName, err2)
}
srcRef = srcRef2
}
splitArr := strings.Split(imgName, ":")
// supports pulling from docker-archive, oci, and registries
if splitArr[0] == "docker-archive" {
tarSource := tarfile.NewSource(splitArr[len(splitArr)-1])
manifest, err := tarSource.LoadTarManifest()
if err != nil {
return errors.Errorf("error retrieving manifest.json: %v", err)
}
// to pull all the images stored in one tar file
for i := range manifest {
if manifest[i].RepoTags != nil {
images = append(images, manifest[i].RepoTags[0])
} else {
// create an image object and use the hex value of the digest as the image ID
// for parsing the store reference
newImg, err := srcRef.NewImage(r.imageContext)
if err != nil {
return err
}
defer newImg.Close()
digest := newImg.ConfigInfo().Digest
if err := digest.Validate(); err == nil {
images = append(images, "@"+digest.Hex())
} else {
return errors.Wrapf(err, "error getting config info")
}
}
}
} else if splitArr[0] == "oci" {
// needs to be implemented in future
return errors.Errorf("oci not supported")
} else {
images = append(images, imgName)
}
policy, err := signature.DefaultPolicy(r.imageContext)
if err != nil {
return err
}
policyContext, err := signature.NewPolicyContext(policy)
if err != nil {
return err
}
defer policyContext.Destroy()
copyOptions := common.GetCopyOptions(r.output, "", nil, nil, common.SigningOptions{})
for _, image := range images {
destRef, err := is.Transport.ParseStoreReference(r.store, image)
if err != nil {
return errors.Errorf("error parsing dest reference name: %v", err)
}
if err = cp.Image(policyContext, destRef, srcRef, copyOptions); err != nil {
return errors.Errorf("error loading image %q: %v", image, err)
}
}
return nil
}
// PushImage pushes the given image to a location described by the given path
func (r *Runtime) PushImage(source string, destination string, options CopyOptions) error {
// PushImage pushes the src image to the destination
//func PushImage(source, destination string, options CopyOptions) error {
if source == "" || destination == "" {
return errors.Wrapf(syscall.EINVAL, "source and destination image names must be specified")
}
// Get the destination Image Reference
dest, err := alltransports.ParseImageName(destination)
if err != nil {
return errors.Wrapf(err, "error getting destination imageReference for %q", destination)
}
policyContext, err := common.GetPolicyContext(options.SignaturePolicyPath)
if err != nil {
return errors.Wrapf(err, "Could not get default policy context for signature policy path %q", options.SignaturePolicyPath)
}
defer policyContext.Destroy()
// Look up the image name and its layer, then build the imagePushData from
// the image
img, err := images.FindImage(r.store, source)
if err != nil {
return errors.Wrapf(err, "error locating image %q for importing settings", source)
}
cd, err := images.ImportCopyDataFromImage(r.store, r.imageContext, img.ID, "", "")
if err != nil {
return err
}
// Give the image we're producing the same ancestors as its source image
cd.FromImage = cd.Docker.ContainerConfig.Image
cd.FromImageID = string(cd.Docker.Parent)
// Prep the layers and manifest for export
src, err := cd.MakeImageRef(manifest.GuessMIMEType(cd.Manifest), options.Compression, img.Names, img.TopLayer, nil)
if err != nil {
return errors.Wrapf(err, "error copying layers and metadata")
}
copyOptions := common.GetCopyOptions(options.ReportWriter, options.SignaturePolicyPath, nil, &options.DockerRegistryOptions, options.SigningOptions)
// Copy the image to the remote destination
err = cp.Image(policyContext, dest, src, copyOptions)
if err != nil {
return errors.Wrapf(err, "Error copying image to the remote destination")
}
return nil
}
// TagImage adds a tag to the given image
func (r *Runtime) TagImage(image *storage.Image, tag string) error {
return ctr.ErrNotImplemented
}
// UntagImage removes a tag from the given image
func (r *Runtime) UntagImage(image *storage.Image, tag string) error {
return ctr.ErrNotImplemented
}
// RemoveImage deletes an image from local storage
// Images being used by running containers cannot be removed
func (r *Runtime) RemoveImage(image *storage.Image) error {
return ctr.ErrNotImplemented
}
// GetImage retrieves an image matching the given name or hash from system
// storage
// If no matching image can be found, an error is returned
func (r *Runtime) GetImage(image string) (*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}
// GetImages retrieves all images present in storage
// 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(filter ...ImageFilter) ([]*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}
// ImportImage imports an OCI format image archive into storage as an image
func (r *Runtime) ImportImage(path string) (*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}

View file

@ -1,4 +1,4 @@
package image
package images
import (
"io"
@ -15,7 +15,7 @@ import (
"github.com/containers/image/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/common"
"github.com/pkg/errors"
)

View file

@ -1,4 +1,4 @@
package image
package images
import (
"encoding/json"
@ -16,7 +16,7 @@ import (
"github.com/containers/storage/pkg/archive"
"github.com/docker/docker/pkg/ioutils"
"github.com/kubernetes-incubator/cri-o/cmd/kpod/docker"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/common"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"

View file

@ -1,4 +1,4 @@
package image
package images
import (
"bytes"

View file

@ -1,4 +1,4 @@
package image
package images
import (
"fmt"
@ -9,7 +9,7 @@ import (
"github.com/containers/image/transports"
"github.com/containers/image/types"
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/libkpod/common"
"github.com/kubernetes-incubator/cri-o/libpod/common"
digest "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
)

View file

@ -1,4 +1,4 @@
package image
package images
import (
"encoding/json"
@ -7,7 +7,7 @@ import (
"github.com/containers/image/docker/reference"
"github.com/containers/image/transports"
"github.com/containers/storage"
"github.com/kubernetes-incubator/cri-o/libkpod/driver"
"github.com/kubernetes-incubator/cri-o/libpod/driver"
digest "github.com/opencontainers/go-digest"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"

View file

@ -1,4 +1,4 @@
package image
package images
import (
"github.com/containers/storage"

View file

@ -1,4 +1,4 @@
package layer
package layers
import cstorage "github.com/containers/storage"

View file

@ -2,6 +2,7 @@ package libpod
import (
"fmt"
"io"
"sync"
"github.com/containers/image/types"
@ -28,6 +29,7 @@ type Runtime struct {
seccompEnabled bool
valid bool
lock sync.RWMutex
output io.Writer
}
// RuntimeConfig contains configuration options used to set up the runtime
@ -212,60 +214,3 @@ func (r *Runtime) LookupPod(idOrName string) (*pod.Pod, error) {
func (r *Runtime) GetPods(filters ...PodFilter) ([]*pod.Pod, error) {
return nil, ctr.ErrNotImplemented
}
// Image API
// 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) bool
// PullImage pulls an image from configured registries
// By default, only the latest tag (or a specific tag if requested) will be
// pulled. If allTags is true, all tags for the requested image will be pulled.
// Signature validation will be performed if the Runtime has been appropriately
// configured
func (r *Runtime) PullImage(image string, allTags bool) (*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}
// PushImage pushes the given image to a location described by the given path
func (r *Runtime) PushImage(image *storage.Image, destination string) error {
return ctr.ErrNotImplemented
}
// TagImage adds a tag to the given image
func (r *Runtime) TagImage(image *storage.Image, tag string) error {
return ctr.ErrNotImplemented
}
// UntagImage removes a tag from the given image
func (r *Runtime) UntagImage(image *storage.Image, tag string) error {
return ctr.ErrNotImplemented
}
// RemoveImage deletes an image from local storage
// Images being used by running containers cannot be removed
func (r *Runtime) RemoveImage(image *storage.Image) error {
return ctr.ErrNotImplemented
}
// GetImage retrieves an image matching the given name or hash from system
// storage
// If no matching image can be found, an error is returned
func (r *Runtime) GetImage(image string) (*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}
// GetImages retrieves all images present in storage
// 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(filter ...ImageFilter) ([]*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}
// ImportImage imports an OCI format image archive into storage as an image
func (r *Runtime) ImportImage(path string) (*storage.Image, error) {
return nil, ctr.ErrNotImplemented
}