github.com/demonoid81/containerd@v1.3.4/contrib/snapshotservice/service.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 snapshotservice
    18  
    19  import (
    20  	"context"
    21  
    22  	snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
    23  	"github.com/containerd/containerd/api/types"
    24  	"github.com/containerd/containerd/errdefs"
    25  	"github.com/containerd/containerd/mount"
    26  	"github.com/containerd/containerd/snapshots"
    27  	ptypes "github.com/gogo/protobuf/types"
    28  )
    29  
    30  var empty = &ptypes.Empty{}
    31  
    32  type service struct {
    33  	sn snapshots.Snapshotter
    34  }
    35  
    36  // FromSnapshotter returns a Snapshot API server from a containerd snapshotter
    37  func FromSnapshotter(sn snapshots.Snapshotter) snapshotsapi.SnapshotsServer {
    38  	return service{sn: sn}
    39  }
    40  
    41  func (s service) Prepare(ctx context.Context, pr *snapshotsapi.PrepareSnapshotRequest) (*snapshotsapi.PrepareSnapshotResponse, error) {
    42  	var opts []snapshots.Opt
    43  	if pr.Labels != nil {
    44  		opts = append(opts, snapshots.WithLabels(pr.Labels))
    45  	}
    46  	mounts, err := s.sn.Prepare(ctx, pr.Key, pr.Parent, opts...)
    47  	if err != nil {
    48  		return nil, errdefs.ToGRPC(err)
    49  	}
    50  
    51  	return &snapshotsapi.PrepareSnapshotResponse{
    52  		Mounts: fromMounts(mounts),
    53  	}, nil
    54  }
    55  
    56  func (s service) View(ctx context.Context, pr *snapshotsapi.ViewSnapshotRequest) (*snapshotsapi.ViewSnapshotResponse, error) {
    57  	var opts []snapshots.Opt
    58  	if pr.Labels != nil {
    59  		opts = append(opts, snapshots.WithLabels(pr.Labels))
    60  	}
    61  	mounts, err := s.sn.View(ctx, pr.Key, pr.Parent, opts...)
    62  	if err != nil {
    63  		return nil, errdefs.ToGRPC(err)
    64  	}
    65  	return &snapshotsapi.ViewSnapshotResponse{
    66  		Mounts: fromMounts(mounts),
    67  	}, nil
    68  }
    69  
    70  func (s service) Mounts(ctx context.Context, mr *snapshotsapi.MountsRequest) (*snapshotsapi.MountsResponse, error) {
    71  	mounts, err := s.sn.Mounts(ctx, mr.Key)
    72  	if err != nil {
    73  		return nil, errdefs.ToGRPC(err)
    74  	}
    75  	return &snapshotsapi.MountsResponse{
    76  		Mounts: fromMounts(mounts),
    77  	}, nil
    78  }
    79  
    80  func (s service) Commit(ctx context.Context, cr *snapshotsapi.CommitSnapshotRequest) (*ptypes.Empty, error) {
    81  	var opts []snapshots.Opt
    82  	if cr.Labels != nil {
    83  		opts = append(opts, snapshots.WithLabels(cr.Labels))
    84  	}
    85  	if err := s.sn.Commit(ctx, cr.Name, cr.Key, opts...); err != nil {
    86  		return nil, errdefs.ToGRPC(err)
    87  	}
    88  
    89  	return empty, nil
    90  }
    91  
    92  func (s service) Remove(ctx context.Context, rr *snapshotsapi.RemoveSnapshotRequest) (*ptypes.Empty, error) {
    93  	if err := s.sn.Remove(ctx, rr.Key); err != nil {
    94  		return nil, errdefs.ToGRPC(err)
    95  	}
    96  
    97  	return empty, nil
    98  }
    99  
   100  func (s service) Stat(ctx context.Context, sr *snapshotsapi.StatSnapshotRequest) (*snapshotsapi.StatSnapshotResponse, error) {
   101  	info, err := s.sn.Stat(ctx, sr.Key)
   102  	if err != nil {
   103  		return nil, errdefs.ToGRPC(err)
   104  	}
   105  
   106  	return &snapshotsapi.StatSnapshotResponse{Info: fromInfo(info)}, nil
   107  }
   108  
   109  func (s service) Update(ctx context.Context, sr *snapshotsapi.UpdateSnapshotRequest) (*snapshotsapi.UpdateSnapshotResponse, error) {
   110  	info, err := s.sn.Update(ctx, toInfo(sr.Info), sr.UpdateMask.GetPaths()...)
   111  	if err != nil {
   112  		return nil, errdefs.ToGRPC(err)
   113  	}
   114  
   115  	return &snapshotsapi.UpdateSnapshotResponse{Info: fromInfo(info)}, nil
   116  }
   117  
   118  func (s service) List(sr *snapshotsapi.ListSnapshotsRequest, ss snapshotsapi.Snapshots_ListServer) error {
   119  	var (
   120  		buffer    []snapshotsapi.Info
   121  		sendBlock = func(block []snapshotsapi.Info) error {
   122  			return ss.Send(&snapshotsapi.ListSnapshotsResponse{
   123  				Info: block,
   124  			})
   125  		}
   126  	)
   127  	err := s.sn.Walk(ss.Context(), func(ctx context.Context, info snapshots.Info) error {
   128  		buffer = append(buffer, fromInfo(info))
   129  
   130  		if len(buffer) >= 100 {
   131  			if err := sendBlock(buffer); err != nil {
   132  				return err
   133  			}
   134  
   135  			buffer = buffer[:0]
   136  		}
   137  
   138  		return nil
   139  	})
   140  	if err != nil {
   141  		return err
   142  	}
   143  	if len(buffer) > 0 {
   144  		// Send remaining infos
   145  		if err := sendBlock(buffer); err != nil {
   146  			return err
   147  		}
   148  	}
   149  
   150  	return nil
   151  
   152  }
   153  
   154  func (s service) Usage(ctx context.Context, ur *snapshotsapi.UsageRequest) (*snapshotsapi.UsageResponse, error) {
   155  	usage, err := s.sn.Usage(ctx, ur.Key)
   156  	if err != nil {
   157  		return nil, errdefs.ToGRPC(err)
   158  	}
   159  
   160  	return &snapshotsapi.UsageResponse{
   161  		Inodes: usage.Inodes,
   162  		Size_:  usage.Size,
   163  	}, nil
   164  }
   165  
   166  func fromKind(kind snapshots.Kind) snapshotsapi.Kind {
   167  	if kind == snapshots.KindActive {
   168  		return snapshotsapi.KindActive
   169  	}
   170  	if kind == snapshots.KindView {
   171  		return snapshotsapi.KindView
   172  	}
   173  	return snapshotsapi.KindCommitted
   174  }
   175  
   176  func fromInfo(info snapshots.Info) snapshotsapi.Info {
   177  	return snapshotsapi.Info{
   178  		Name:      info.Name,
   179  		Parent:    info.Parent,
   180  		Kind:      fromKind(info.Kind),
   181  		CreatedAt: info.Created,
   182  		UpdatedAt: info.Updated,
   183  		Labels:    info.Labels,
   184  	}
   185  }
   186  
   187  func fromMounts(mounts []mount.Mount) []*types.Mount {
   188  	out := make([]*types.Mount, len(mounts))
   189  	for i, m := range mounts {
   190  		out[i] = &types.Mount{
   191  			Type:    m.Type,
   192  			Source:  m.Source,
   193  			Options: m.Options,
   194  		}
   195  	}
   196  	return out
   197  }
   198  
   199  func toInfo(info snapshotsapi.Info) snapshots.Info {
   200  	return snapshots.Info{
   201  		Name:    info.Name,
   202  		Parent:  info.Parent,
   203  		Kind:    toKind(info.Kind),
   204  		Created: info.CreatedAt,
   205  		Updated: info.UpdatedAt,
   206  		Labels:  info.Labels,
   207  	}
   208  }
   209  
   210  func toKind(kind snapshotsapi.Kind) snapshots.Kind {
   211  	if kind == snapshotsapi.KindActive {
   212  		return snapshots.KindActive
   213  	}
   214  	if kind == snapshotsapi.KindView {
   215  		return snapshots.KindView
   216  	}
   217  	return snapshots.KindCommitted
   218  }