containerd/image_store.go
Derek McGowan 3f1a61f76a
Add synchronous image delete
Synchronous image delete provides an option image delete to wait
until the next garbage collection deletes after an image is removed
before returning success to the caller.

Signed-off-by: Derek McGowan <derek@mcgstyle.net>
2017-11-20 17:08:35 -08:00

137 lines
3.3 KiB
Go

package containerd
import (
"context"
imagesapi "github.com/containerd/containerd/api/services/images/v1"
"github.com/containerd/containerd/api/types"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/images"
ptypes "github.com/gogo/protobuf/types"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
type remoteImages struct {
client imagesapi.ImagesClient
}
// NewImageStoreFromClient returns a new image store client
func NewImageStoreFromClient(client imagesapi.ImagesClient) images.Store {
return &remoteImages{
client: client,
}
}
func (s *remoteImages) Get(ctx context.Context, name string) (images.Image, error) {
resp, err := s.client.Get(ctx, &imagesapi.GetImageRequest{
Name: name,
})
if err != nil {
return images.Image{}, errdefs.FromGRPC(err)
}
return imageFromProto(resp.Image), nil
}
func (s *remoteImages) List(ctx context.Context, filters ...string) ([]images.Image, error) {
resp, err := s.client.List(ctx, &imagesapi.ListImagesRequest{
Filters: filters,
})
if err != nil {
return nil, errdefs.FromGRPC(err)
}
return imagesFromProto(resp.Images), nil
}
func (s *remoteImages) Create(ctx context.Context, image images.Image) (images.Image, error) {
created, err := s.client.Create(ctx, &imagesapi.CreateImageRequest{
Image: imageToProto(&image),
})
if err != nil {
return images.Image{}, errdefs.FromGRPC(err)
}
return imageFromProto(&created.Image), nil
}
func (s *remoteImages) Update(ctx context.Context, image images.Image, fieldpaths ...string) (images.Image, error) {
var updateMask *ptypes.FieldMask
if len(fieldpaths) > 0 {
updateMask = &ptypes.FieldMask{
Paths: fieldpaths,
}
}
updated, err := s.client.Update(ctx, &imagesapi.UpdateImageRequest{
Image: imageToProto(&image),
UpdateMask: updateMask,
})
if err != nil {
return images.Image{}, errdefs.FromGRPC(err)
}
return imageFromProto(&updated.Image), nil
}
func (s *remoteImages) Delete(ctx context.Context, name string, opts ...images.DeleteOpt) error {
var do images.DeleteOptions
for _, opt := range opts {
if err := opt(ctx, &do); err != nil {
return err
}
}
_, err := s.client.Delete(ctx, &imagesapi.DeleteImageRequest{
Name: name,
Sync: do.Synchronous,
})
return errdefs.FromGRPC(err)
}
func imageToProto(image *images.Image) imagesapi.Image {
return imagesapi.Image{
Name: image.Name,
Labels: image.Labels,
Target: descToProto(&image.Target),
CreatedAt: image.CreatedAt,
UpdatedAt: image.UpdatedAt,
}
}
func imageFromProto(imagepb *imagesapi.Image) images.Image {
return images.Image{
Name: imagepb.Name,
Labels: imagepb.Labels,
Target: descFromProto(&imagepb.Target),
CreatedAt: imagepb.CreatedAt,
UpdatedAt: imagepb.UpdatedAt,
}
}
func imagesFromProto(imagespb []imagesapi.Image) []images.Image {
var images []images.Image
for _, image := range imagespb {
images = append(images, imageFromProto(&image))
}
return images
}
func descFromProto(desc *types.Descriptor) ocispec.Descriptor {
return ocispec.Descriptor{
MediaType: desc.MediaType,
Size: desc.Size_,
Digest: desc.Digest,
}
}
func descToProto(desc *ocispec.Descriptor) types.Descriptor {
return types.Descriptor{
MediaType: desc.MediaType,
Size_: desc.Size,
Digest: desc.Digest,
}
}