github.com/containerd/Containerd@v1.4.13/services/images/local.go (about)

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package images
    18  
    19  import (
    20  	"context"
    21  
    22  	eventstypes "github.com/containerd/containerd/api/events"
    23  	imagesapi "github.com/containerd/containerd/api/services/images/v1"
    24  	"github.com/containerd/containerd/errdefs"
    25  	"github.com/containerd/containerd/events"
    26  	"github.com/containerd/containerd/gc"
    27  	"github.com/containerd/containerd/images"
    28  	"github.com/containerd/containerd/log"
    29  	"github.com/containerd/containerd/metadata"
    30  	"github.com/containerd/containerd/plugin"
    31  	"github.com/containerd/containerd/services"
    32  	ptypes "github.com/gogo/protobuf/types"
    33  	"google.golang.org/grpc"
    34  	"google.golang.org/grpc/codes"
    35  	"google.golang.org/grpc/status"
    36  )
    37  
    38  func init() {
    39  	plugin.Register(&plugin.Registration{
    40  		Type: plugin.ServicePlugin,
    41  		ID:   services.ImagesService,
    42  		Requires: []plugin.Type{
    43  			plugin.MetadataPlugin,
    44  			plugin.GCPlugin,
    45  		},
    46  		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
    47  			m, err := ic.Get(plugin.MetadataPlugin)
    48  			if err != nil {
    49  				return nil, err
    50  			}
    51  			g, err := ic.Get(plugin.GCPlugin)
    52  			if err != nil {
    53  				return nil, err
    54  			}
    55  
    56  			return &local{
    57  				store:     metadata.NewImageStore(m.(*metadata.DB)),
    58  				publisher: ic.Events,
    59  				gc:        g.(gcScheduler),
    60  			}, nil
    61  		},
    62  	})
    63  }
    64  
    65  type gcScheduler interface {
    66  	ScheduleAndWait(context.Context) (gc.Stats, error)
    67  }
    68  
    69  type local struct {
    70  	store     images.Store
    71  	gc        gcScheduler
    72  	publisher events.Publisher
    73  }
    74  
    75  var _ imagesapi.ImagesClient = &local{}
    76  
    77  func (l *local) Get(ctx context.Context, req *imagesapi.GetImageRequest, _ ...grpc.CallOption) (*imagesapi.GetImageResponse, error) {
    78  	image, err := l.store.Get(ctx, req.Name)
    79  	if err != nil {
    80  		return nil, errdefs.ToGRPC(err)
    81  	}
    82  
    83  	imagepb := imageToProto(&image)
    84  	return &imagesapi.GetImageResponse{
    85  		Image: &imagepb,
    86  	}, nil
    87  }
    88  
    89  func (l *local) List(ctx context.Context, req *imagesapi.ListImagesRequest, _ ...grpc.CallOption) (*imagesapi.ListImagesResponse, error) {
    90  	images, err := l.store.List(ctx, req.Filters...)
    91  	if err != nil {
    92  		return nil, errdefs.ToGRPC(err)
    93  	}
    94  
    95  	return &imagesapi.ListImagesResponse{
    96  		Images: imagesToProto(images),
    97  	}, nil
    98  }
    99  
   100  func (l *local) Create(ctx context.Context, req *imagesapi.CreateImageRequest, _ ...grpc.CallOption) (*imagesapi.CreateImageResponse, error) {
   101  	log.G(ctx).WithField("name", req.Image.Name).WithField("target", req.Image.Target.Digest).Debugf("create image")
   102  	if req.Image.Name == "" {
   103  		return nil, status.Errorf(codes.InvalidArgument, "Image.Name required")
   104  	}
   105  
   106  	var (
   107  		image = imageFromProto(&req.Image)
   108  		resp  imagesapi.CreateImageResponse
   109  	)
   110  	created, err := l.store.Create(ctx, image)
   111  	if err != nil {
   112  		return nil, errdefs.ToGRPC(err)
   113  	}
   114  
   115  	resp.Image = imageToProto(&created)
   116  
   117  	if err := l.publisher.Publish(ctx, "/images/create", &eventstypes.ImageCreate{
   118  		Name:   resp.Image.Name,
   119  		Labels: resp.Image.Labels,
   120  	}); err != nil {
   121  		return nil, err
   122  	}
   123  
   124  	return &resp, nil
   125  
   126  }
   127  
   128  func (l *local) Update(ctx context.Context, req *imagesapi.UpdateImageRequest, _ ...grpc.CallOption) (*imagesapi.UpdateImageResponse, error) {
   129  	if req.Image.Name == "" {
   130  		return nil, status.Errorf(codes.InvalidArgument, "Image.Name required")
   131  	}
   132  
   133  	var (
   134  		image      = imageFromProto(&req.Image)
   135  		resp       imagesapi.UpdateImageResponse
   136  		fieldpaths []string
   137  	)
   138  
   139  	if req.UpdateMask != nil && len(req.UpdateMask.Paths) > 0 {
   140  		fieldpaths = append(fieldpaths, req.UpdateMask.Paths...)
   141  	}
   142  
   143  	updated, err := l.store.Update(ctx, image, fieldpaths...)
   144  	if err != nil {
   145  		return nil, errdefs.ToGRPC(err)
   146  	}
   147  
   148  	resp.Image = imageToProto(&updated)
   149  
   150  	if err := l.publisher.Publish(ctx, "/images/update", &eventstypes.ImageUpdate{
   151  		Name:   resp.Image.Name,
   152  		Labels: resp.Image.Labels,
   153  	}); err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	return &resp, nil
   158  }
   159  
   160  func (l *local) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest, _ ...grpc.CallOption) (*ptypes.Empty, error) {
   161  	log.G(ctx).WithField("name", req.Name).Debugf("delete image")
   162  
   163  	if err := l.store.Delete(ctx, req.Name); err != nil {
   164  		return nil, errdefs.ToGRPC(err)
   165  	}
   166  
   167  	if err := l.publisher.Publish(ctx, "/images/delete", &eventstypes.ImageDelete{
   168  		Name: req.Name,
   169  	}); err != nil {
   170  		return nil, err
   171  	}
   172  
   173  	if req.Sync {
   174  		if _, err := l.gc.ScheduleAndWait(ctx); err != nil {
   175  			return nil, err
   176  		}
   177  	}
   178  
   179  	return &ptypes.Empty{}, nil
   180  }