client: Add helper function which checks if an image is unpacked

Signed-off-by: Jess Valarezo <valarezo.jessica@gmail.com>
This commit is contained in:
Jess Valarezo 2017-10-20 16:33:22 -07:00
parent e2f9fbfe71
commit 1552ee23da
3 changed files with 102 additions and 12 deletions

View File

@ -177,8 +177,9 @@ var setLabelsCommand = cli.Command{
var checkCommand = cli.Command{
Name: "check",
Usage: "check that an image has all content available locally",
ArgsUsage: "<ref> [<ref>, ...]",
ArgsUsage: "[flags] <ref> [<ref>, ...]",
Description: "check that an image has all content available locally",
Flags: commands.SnapshotterFlags,
Action: func(context *cli.Context) error {
var (
exitErr error
@ -189,14 +190,13 @@ var checkCommand = cli.Command{
}
defer cancel()
var (
imageStore = client.ImageService()
contentStore = client.ContentStore()
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
)
fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSTATUS\tSIZE\t")
fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSTATUS\tSIZE\tUNPACKED\t")
args := []string(context.Args())
imageList, err := imageStore.List(ctx, args...)
imageList, err := client.ListImages(ctx, args...)
if err != nil {
return errors.Wrap(err, "failed listing images")
}
@ -209,12 +209,12 @@ var checkCommand = cli.Command{
presentSize int64
)
available, required, present, missing, err := images.Check(ctx, contentStore, image.Target, platforms.Default())
available, required, present, missing, err := images.Check(ctx, contentStore, image.Target(), platforms.Default())
if err != nil {
if exitErr == nil {
exitErr = errors.Wrapf(err, "unable to check %v", image.Name)
exitErr = errors.Wrapf(err, "unable to check %v", image.Name())
}
log.G(ctx).WithError(err).Errorf("unable to check %v", image.Name)
log.G(ctx).WithError(err).Errorf("unable to check %v", image.Name())
status = "error"
}
@ -242,12 +242,21 @@ var checkCommand = cli.Command{
size = "-"
}
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t\n",
image.Name,
image.Target.MediaType,
image.Target.Digest,
unpacked, err := image.IsUnpacked(ctx, context.String("snapshotter"))
if err != nil {
if exitErr == nil {
exitErr = errors.Wrapf(err, "unable to check unpack for %v", image.Name())
}
log.G(ctx).WithError(err).Errorf("unable to check unpack for %v", image.Name())
}
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%t\n",
image.Name(),
image.Target().MediaType,
image.Target().Digest,
status,
size)
size,
unpacked)
}
tw.Flush()

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/rootfs"
@ -30,6 +31,8 @@ type Image interface {
Size(ctx context.Context) (int64, error)
// Config descriptor for the image.
Config(ctx context.Context) (ocispec.Descriptor, error)
// IsUnpacked returns whether or not an image is unpacked.
IsUnpacked(context.Context, string) (bool, error)
}
var _ = (Image)(&image{})
@ -63,6 +66,26 @@ func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) {
return i.i.Config(ctx, provider, platforms.Default())
}
func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) {
sn := i.client.SnapshotService(snapshotterName)
cs := i.client.ContentStore()
diffs, err := i.i.RootFS(ctx, cs, platforms.Default())
if err != nil {
return false, err
}
chainID := identity.ChainID(diffs)
_, err = sn.Stat(ctx, chainID.String())
if err == nil {
return true, nil
} else if !errdefs.IsNotFound(err) {
return false, err
}
return false, nil
}
func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
layers, err := i.getLayers(ctx, platforms.Default())
if err != nil {

58
image_test.go Normal file
View File

@ -0,0 +1,58 @@
package containerd
import (
"runtime"
"testing"
"github.com/containerd/containerd/errdefs"
)
func TestImageIsUnpacked(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip()
}
const imageName = "docker.io/library/busybox:latest"
ctx, cancel := testContext()
defer cancel()
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
// Cleanup
err = client.ImageService().Delete(ctx, imageName)
if err != nil && !errdefs.IsNotFound(err) {
t.Fatal(err)
}
// By default pull does not unpack an image
image, err := client.Pull(ctx, imageName)
if err != nil {
t.Fatal(err)
}
// Check that image is not unpacked
unpacked, err := image.IsUnpacked(ctx, DefaultSnapshotter)
if err != nil {
t.Fatal(err)
}
if unpacked {
t.Fatalf("image should not be unpacked")
}
// Check that image is unpacked
err = image.Unpack(ctx, DefaultSnapshotter)
if err != nil {
t.Fatal(err)
}
unpacked, err = image.IsUnpacked(ctx, DefaultSnapshotter)
if err != nil {
t.Fatal(err)
}
if !unpacked {
t.Fatalf("image should be unpacked")
}
}