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:
parent
e2f9fbfe71
commit
1552ee23da
@ -177,8 +177,9 @@ var setLabelsCommand = cli.Command{
|
|||||||
var checkCommand = cli.Command{
|
var checkCommand = cli.Command{
|
||||||
Name: "check",
|
Name: "check",
|
||||||
Usage: "check that an image has all content available locally",
|
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",
|
Description: "check that an image has all content available locally",
|
||||||
|
Flags: commands.SnapshotterFlags,
|
||||||
Action: func(context *cli.Context) error {
|
Action: func(context *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
exitErr error
|
exitErr error
|
||||||
@ -189,14 +190,13 @@ var checkCommand = cli.Command{
|
|||||||
}
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
var (
|
var (
|
||||||
imageStore = client.ImageService()
|
|
||||||
contentStore = client.ContentStore()
|
contentStore = client.ContentStore()
|
||||||
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
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())
|
args := []string(context.Args())
|
||||||
imageList, err := imageStore.List(ctx, args...)
|
imageList, err := client.ListImages(ctx, args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed listing images")
|
return errors.Wrap(err, "failed listing images")
|
||||||
}
|
}
|
||||||
@ -209,12 +209,12 @@ var checkCommand = cli.Command{
|
|||||||
presentSize int64
|
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 err != nil {
|
||||||
if exitErr == 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"
|
status = "error"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,12 +242,21 @@ var checkCommand = cli.Command{
|
|||||||
size = "-"
|
size = "-"
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t\n",
|
unpacked, err := image.IsUnpacked(ctx, context.String("snapshotter"))
|
||||||
image.Name,
|
if err != nil {
|
||||||
image.Target.MediaType,
|
if exitErr == nil {
|
||||||
image.Target.Digest,
|
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,
|
status,
|
||||||
size)
|
size,
|
||||||
|
unpacked)
|
||||||
}
|
}
|
||||||
tw.Flush()
|
tw.Flush()
|
||||||
|
|
||||||
|
23
image.go
23
image.go
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/errdefs"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/platforms"
|
"github.com/containerd/containerd/platforms"
|
||||||
"github.com/containerd/containerd/rootfs"
|
"github.com/containerd/containerd/rootfs"
|
||||||
@ -30,6 +31,8 @@ type Image interface {
|
|||||||
Size(ctx context.Context) (int64, error)
|
Size(ctx context.Context) (int64, error)
|
||||||
// Config descriptor for the image.
|
// Config descriptor for the image.
|
||||||
Config(ctx context.Context) (ocispec.Descriptor, error)
|
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{})
|
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())
|
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 {
|
func (i *image) Unpack(ctx context.Context, snapshotterName string) error {
|
||||||
layers, err := i.getLayers(ctx, platforms.Default())
|
layers, err := i.getLayers(ctx, platforms.Default())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
58
image_test.go
Normal file
58
image_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user