From e18e962238e86df4e843525354ac0d4d3b9820af Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Thu, 31 Aug 2017 11:17:21 -0400 Subject: [PATCH 1/2] 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 --- cmd/kpod/history.go | 2 +- cmd/kpod/images.go | 12 +- cmd/kpod/inspect.go | 6 +- cmd/kpod/load.go | 6 +- cmd/kpod/pull.go | 4 +- cmd/kpod/push.go | 4 +- cmd/kpod/rmi.go | 10 +- cmd/kpod/save.go | 6 +- cmd/kpod/stats.go | 4 +- cmd/kpod/tag.go | 4 +- libkpod/container_data.go | 6 +- libkpod/diff.go | 8 +- {libkpod => libpod}/common/common.go | 0 .../common/docker_registry_options.go | 0 .../common/output_interfaces.go | 0 {libkpod => libpod}/common/signing_options.go | 0 {libkpod => libpod}/driver/driver.go | 0 libpod/image.go | 223 ++++++++++++++++++ {libkpod/image => libpod/images}/copy.go | 4 +- {libkpod/image => libpod/images}/copy_data.go | 4 +- {libkpod/image => libpod/images}/copy_ref.go | 2 +- {libkpod/image => libpod/images}/image.go | 4 +- .../image => libpod/images}/image_data.go | 4 +- {libkpod/image => libpod/images}/rmi.go | 2 +- {libkpod/layer => libpod/layers}/layer.go | 2 +- libpod/runtime.go | 59 +---- 26 files changed, 272 insertions(+), 104 deletions(-) rename {libkpod => libpod}/common/common.go (100%) rename {libkpod => libpod}/common/docker_registry_options.go (100%) rename {libkpod => libpod}/common/output_interfaces.go (100%) rename {libkpod => libpod}/common/signing_options.go (100%) rename {libkpod => libpod}/driver/driver.go (100%) create mode 100644 libpod/image.go rename {libkpod/image => libpod/images}/copy.go (98%) rename {libkpod/image => libpod/images}/copy_data.go (99%) rename {libkpod/image => libpod/images}/copy_ref.go (99%) rename {libkpod/image => libpod/images}/image.go (99%) rename {libkpod/image => libpod/images}/image_data.go (98%) rename {libkpod/image => libpod/images}/rmi.go (98%) rename {libkpod/layer => libpod/layers}/layer.go (94%) diff --git a/cmd/kpod/history.go b/cmd/kpod/history.go index 4c83213c..9fb00263 100644 --- a/cmd/kpod/history.go +++ b/cmd/kpod/history.go @@ -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" diff --git a/cmd/kpod/images.go b/cmd/kpod/images.go index 375e7cfe..e1eb7660 100644 --- a/cmd/kpod/images.go +++ b/cmd/kpod/images.go @@ -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) } diff --git a/cmd/kpod/inspect.go b/cmd/kpod/inspect.go index 285d5e7d..d3411d3d 100644 --- a/cmd/kpod/inspect.go +++ b/cmd/kpod/inspect.go @@ -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") } diff --git a/cmd/kpod/load.go b/cmd/kpod/load.go index 6c2eea53..f4b75941 100644 --- a/cmd/kpod/load.go +++ b/cmd/kpod/load.go @@ -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) } diff --git a/cmd/kpod/pull.go b/cmd/kpod/pull.go index 89f74ee3..6beb8a84 100644 --- a/cmd/kpod/pull.go +++ b/cmd/kpod/pull.go @@ -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) } diff --git a/cmd/kpod/push.go b/cmd/kpod/push.go index 2091a872..e559d5e2 100644 --- a/cmd/kpod/push.go +++ b/cmd/kpod/push.go @@ -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) } diff --git a/cmd/kpod/rmi.go b/cmd/kpod/rmi.go index c7752fc1..2e83ee8b 100644 --- a/cmd/kpod/rmi.go +++ b/cmd/kpod/rmi.go @@ -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 } diff --git a/cmd/kpod/save.go b/cmd/kpod/save.go index 8c7edcfb..97d42f70 100644 --- a/cmd/kpod/save.go +++ b/cmd/kpod/save.go @@ -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) } } diff --git a/cmd/kpod/stats.go b/cmd/kpod/stats.go index 416acc93..b3ea6879 100644 --- a/cmd/kpod/stats.go +++ b/cmd/kpod/stats.go @@ -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 { diff --git a/cmd/kpod/tag.go b/cmd/kpod/tag.go index c691dd0e..4e92c310 100644 --- a/cmd/kpod/tag.go +++ b/cmd/kpod/tag.go @@ -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 } diff --git a/libkpod/container_data.go b/libkpod/container_data.go index 96556b25..21843d40 100644 --- a/libkpod/container_data.go +++ b/libkpod/container_data.go @@ -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") } diff --git a/libkpod/diff.go b/libkpod/diff.go index 83a00b2b..281592c8 100644 --- a/libkpod/diff.go +++ b/libkpod/diff.go @@ -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) } diff --git a/libkpod/common/common.go b/libpod/common/common.go similarity index 100% rename from libkpod/common/common.go rename to libpod/common/common.go diff --git a/libkpod/common/docker_registry_options.go b/libpod/common/docker_registry_options.go similarity index 100% rename from libkpod/common/docker_registry_options.go rename to libpod/common/docker_registry_options.go diff --git a/libkpod/common/output_interfaces.go b/libpod/common/output_interfaces.go similarity index 100% rename from libkpod/common/output_interfaces.go rename to libpod/common/output_interfaces.go diff --git a/libkpod/common/signing_options.go b/libpod/common/signing_options.go similarity index 100% rename from libkpod/common/signing_options.go rename to libpod/common/signing_options.go diff --git a/libkpod/driver/driver.go b/libpod/driver/driver.go similarity index 100% rename from libkpod/driver/driver.go rename to libpod/driver/driver.go diff --git a/libpod/image.go b/libpod/image.go new file mode 100644 index 00000000..ea9de972 --- /dev/null +++ b/libpod/image.go @@ -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 +} diff --git a/libkpod/image/copy.go b/libpod/images/copy.go similarity index 98% rename from libkpod/image/copy.go rename to libpod/images/copy.go index 7b2081a1..8a9688e0 100644 --- a/libkpod/image/copy.go +++ b/libpod/images/copy.go @@ -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" ) diff --git a/libkpod/image/copy_data.go b/libpod/images/copy_data.go similarity index 99% rename from libkpod/image/copy_data.go rename to libpod/images/copy_data.go index eadc6621..92cd3256 100644 --- a/libkpod/image/copy_data.go +++ b/libpod/images/copy_data.go @@ -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" diff --git a/libkpod/image/copy_ref.go b/libpod/images/copy_ref.go similarity index 99% rename from libkpod/image/copy_ref.go rename to libpod/images/copy_ref.go index 9ab88c25..fc4371aa 100644 --- a/libkpod/image/copy_ref.go +++ b/libpod/images/copy_ref.go @@ -1,4 +1,4 @@ -package image +package images import ( "bytes" diff --git a/libkpod/image/image.go b/libpod/images/image.go similarity index 99% rename from libkpod/image/image.go rename to libpod/images/image.go index 20e6f5d9..191b4392 100644 --- a/libkpod/image/image.go +++ b/libpod/images/image.go @@ -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" ) diff --git a/libkpod/image/image_data.go b/libpod/images/image_data.go similarity index 98% rename from libkpod/image/image_data.go rename to libpod/images/image_data.go index 900ff3ff..f187bc4d 100644 --- a/libkpod/image/image_data.go +++ b/libpod/images/image_data.go @@ -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" diff --git a/libkpod/image/rmi.go b/libpod/images/rmi.go similarity index 98% rename from libkpod/image/rmi.go rename to libpod/images/rmi.go index 1e968d18..b3b0459e 100644 --- a/libkpod/image/rmi.go +++ b/libpod/images/rmi.go @@ -1,4 +1,4 @@ -package image +package images import ( "github.com/containers/storage" diff --git a/libkpod/layer/layer.go b/libpod/layers/layer.go similarity index 94% rename from libkpod/layer/layer.go rename to libpod/layers/layer.go index a7996350..865cbe70 100644 --- a/libkpod/layer/layer.go +++ b/libpod/layers/layer.go @@ -1,4 +1,4 @@ -package layer +package layers import cstorage "github.com/containers/storage" diff --git a/libpod/runtime.go b/libpod/runtime.go index f2c4c7c5..1eebb7ee 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -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 -} From 9f282717da9f293558098da3aedb763f789b05b5 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 6 Sep 2017 14:28:59 +0000 Subject: [PATCH 2/2] Begin converting kpod pull to use libpod/runtime We want to drop brute force mechainism for handling image movement, this patch experiments with moving kpod pull to use new libpod interfaces. Signed-off-by: Daniel J Walsh --- cmd/kpod/common.go | 18 ++++++++++++++++++ cmd/kpod/pull.go | 20 +++++--------------- cmd/kpod/push.go | 4 ++-- libpod/image.go | 17 ++++++----------- libpod/runtime.go | 2 -- 5 files changed, 31 insertions(+), 30 deletions(-) diff --git a/cmd/kpod/common.go b/cmd/kpod/common.go index 2a7d92ea..1c1503e2 100644 --- a/cmd/kpod/common.go +++ b/cmd/kpod/common.go @@ -8,7 +8,9 @@ import ( "github.com/containers/storage" "github.com/fatih/camelcase" "github.com/kubernetes-incubator/cri-o/libkpod" + "github.com/kubernetes-incubator/cri-o/libpod" "github.com/kubernetes-incubator/cri-o/server" + "github.com/pkg/errors" "github.com/urfave/cli" ) @@ -32,6 +34,22 @@ func getStore(c *libkpod.Config) (storage.Store, error) { return store, nil } +func getRuntime(c *cli.Context) (*libpod.Runtime, error) { + + config, err := getConfig(c) + if err != nil { + return nil, errors.Wrapf(err, "could not get config") + } + + options := storage.DefaultStoreOptions + options.GraphRoot = config.Root + options.RunRoot = config.RunRoot + options.GraphDriverName = config.Storage + options.GraphDriverOptions = config.StorageOptions + + return libpod.NewRuntime(libpod.WithStorageConfig(options)) +} + func shutdownStores() { for store := range stores { if _, err := store.Shutdown(false); err != nil { diff --git a/cmd/kpod/pull.go b/cmd/kpod/pull.go index 6beb8a84..69f31def 100644 --- a/cmd/kpod/pull.go +++ b/cmd/kpod/pull.go @@ -1,8 +1,8 @@ package main import ( - "github.com/kubernetes-incubator/cri-o/libkpod/common" - "github.com/kubernetes-incubator/cri-o/libpod/images" + "os" + "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/urfave/cli" @@ -45,21 +45,11 @@ func pullCmd(c *cli.Context) error { } image := args[0] - config, err := getConfig(c) + runtime, err := getRuntime(c) if err != nil { - return errors.Wrapf(err, "could not get config") + return errors.Wrapf(err, "could not create runtime") } - store, err := getStore(config) - if err != nil { - return err - } - - allTags := c.Bool("all-tags") - - systemContext := common.GetSystemContext("") - - err = images.PullImage(store, image, allTags, false, systemContext) - if err != nil { + if err := runtime.PullImage(image, c.Bool("all-tags"), os.Stdout); err != nil { return errors.Errorf("error pulling image from %q: %v", image, err) } return nil diff --git a/cmd/kpod/push.go b/cmd/kpod/push.go index e559d5e2..be9d3a1e 100644 --- a/cmd/kpod/push.go +++ b/cmd/kpod/push.go @@ -6,7 +6,7 @@ import ( "github.com/containers/image/types" "github.com/containers/storage/pkg/archive" - "github.com/kubernetes-incubator/cri-o/libkpod/common" + "github.com/kubernetes-incubator/cri-o/libpod/common" "github.com/kubernetes-incubator/cri-o/libpod/images" "github.com/pkg/errors" "github.com/urfave/cli" @@ -103,7 +103,7 @@ func pushCmd(c *cli.Context) error { return err } - options := libkpodimage.CopyOptions{ + options := images.CopyOptions{ Compression: archive.Uncompressed, SignaturePolicyPath: signaturePolicy, Store: store, diff --git a/libpod/image.go b/libpod/image.go index ea9de972..cbc52d49 100644 --- a/libpod/image.go +++ b/libpod/image.go @@ -33,11 +33,6 @@ type CopyOptions struct { // 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. @@ -60,7 +55,7 @@ type ImageFilter func(*storage.Image) bool // 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 { +func (r *Runtime) PullImage(imgName string, allTags bool, reportWriter io.Writer) error { // PullImage copies the image from the source to the destination var ( images []string @@ -123,7 +118,7 @@ func (r *Runtime) PullImage(imgName string, allTags bool) error { } defer policyContext.Destroy() - copyOptions := common.GetCopyOptions(r.output, "", nil, nil, common.SigningOptions{}) + copyOptions := common.GetCopyOptions(reportWriter, "", nil, nil, common.SigningOptions{}) for _, image := range images { destRef, err := is.Transport.ParseStoreReference(r.store, image) @@ -138,7 +133,7 @@ func (r *Runtime) PullImage(imgName string, allTags bool) error { } // PushImage pushes the given image to a location described by the given path -func (r *Runtime) PushImage(source string, destination string, options CopyOptions) error { +func (r *Runtime) PushImage(source string, destination string, options CopyOptions, reportWriter io.Writer) error { // PushImage pushes the src image to the destination //func PushImage(source, destination string, options CopyOptions) error { if source == "" || destination == "" { @@ -151,9 +146,9 @@ func (r *Runtime) PushImage(source string, destination string, options CopyOptio return errors.Wrapf(err, "error getting destination imageReference for %q", destination) } - policyContext, err := common.GetPolicyContext(options.SignaturePolicyPath) + policyContext, err := common.GetPolicyContext(r.GetConfig().SignaturePolicyPath) if err != nil { - return errors.Wrapf(err, "Could not get default policy context for signature policy path %q", options.SignaturePolicyPath) + return errors.Wrapf(err, "Could not get default policy context for signature policy path %q", r.GetConfig().SignaturePolicyPath) } defer policyContext.Destroy() // Look up the image name and its layer, then build the imagePushData from @@ -176,7 +171,7 @@ func (r *Runtime) PushImage(source string, destination string, options CopyOptio return errors.Wrapf(err, "error copying layers and metadata") } - copyOptions := common.GetCopyOptions(options.ReportWriter, options.SignaturePolicyPath, nil, &options.DockerRegistryOptions, options.SigningOptions) + copyOptions := common.GetCopyOptions(reportWriter, r.GetConfig().SignaturePolicyPath, nil, &options.DockerRegistryOptions, options.SigningOptions) // Copy the image to the remote destination err = cp.Image(policyContext, dest, src, copyOptions) diff --git a/libpod/runtime.go b/libpod/runtime.go index 1eebb7ee..05abda40 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -2,7 +2,6 @@ package libpod import ( "fmt" - "io" "sync" "github.com/containers/image/types" @@ -29,7 +28,6 @@ type Runtime struct { seccompEnabled bool valid bool lock sync.RWMutex - output io.Writer } // RuntimeConfig contains configuration options used to set up the runtime