github.com/containerd/Containerd@v1.4.13/snapshots/proxy/proxy.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 proxy
    18  
    19  import (
    20  	"context"
    21  	"io"
    22  
    23  	snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1"
    24  	"github.com/containerd/containerd/api/types"
    25  	"github.com/containerd/containerd/errdefs"
    26  	"github.com/containerd/containerd/mount"
    27  	"github.com/containerd/containerd/snapshots"
    28  	protobuftypes "github.com/gogo/protobuf/types"
    29  )
    30  
    31  // NewSnapshotter returns a new Snapshotter which communicates over a GRPC
    32  // connection using the containerd snapshot GRPC API.
    33  func NewSnapshotter(client snapshotsapi.SnapshotsClient, snapshotterName string) snapshots.Snapshotter {
    34  	return &proxySnapshotter{
    35  		client:          client,
    36  		snapshotterName: snapshotterName,
    37  	}
    38  }
    39  
    40  type proxySnapshotter struct {
    41  	client          snapshotsapi.SnapshotsClient
    42  	snapshotterName string
    43  }
    44  
    45  func (p *proxySnapshotter) Stat(ctx context.Context, key string) (snapshots.Info, error) {
    46  	resp, err := p.client.Stat(ctx,
    47  		&snapshotsapi.StatSnapshotRequest{
    48  			Snapshotter: p.snapshotterName,
    49  			Key:         key,
    50  		})
    51  	if err != nil {
    52  		return snapshots.Info{}, errdefs.FromGRPC(err)
    53  	}
    54  	return toInfo(resp.Info), nil
    55  }
    56  
    57  func (p *proxySnapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) {
    58  	resp, err := p.client.Update(ctx,
    59  		&snapshotsapi.UpdateSnapshotRequest{
    60  			Snapshotter: p.snapshotterName,
    61  			Info:        fromInfo(info),
    62  			UpdateMask: &protobuftypes.FieldMask{
    63  				Paths: fieldpaths,
    64  			},
    65  		})
    66  	if err != nil {
    67  		return snapshots.Info{}, errdefs.FromGRPC(err)
    68  	}
    69  	return toInfo(resp.Info), nil
    70  }
    71  
    72  func (p *proxySnapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) {
    73  	resp, err := p.client.Usage(ctx, &snapshotsapi.UsageRequest{
    74  		Snapshotter: p.snapshotterName,
    75  		Key:         key,
    76  	})
    77  	if err != nil {
    78  		return snapshots.Usage{}, errdefs.FromGRPC(err)
    79  	}
    80  	return toUsage(resp), nil
    81  }
    82  
    83  func (p *proxySnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
    84  	resp, err := p.client.Mounts(ctx, &snapshotsapi.MountsRequest{
    85  		Snapshotter: p.snapshotterName,
    86  		Key:         key,
    87  	})
    88  	if err != nil {
    89  		return nil, errdefs.FromGRPC(err)
    90  	}
    91  	return toMounts(resp.Mounts), nil
    92  }
    93  
    94  func (p *proxySnapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
    95  	var local snapshots.Info
    96  	for _, opt := range opts {
    97  		if err := opt(&local); err != nil {
    98  			return nil, err
    99  		}
   100  	}
   101  	resp, err := p.client.Prepare(ctx, &snapshotsapi.PrepareSnapshotRequest{
   102  		Snapshotter: p.snapshotterName,
   103  		Key:         key,
   104  		Parent:      parent,
   105  		Labels:      local.Labels,
   106  	})
   107  	if err != nil {
   108  		return nil, errdefs.FromGRPC(err)
   109  	}
   110  	return toMounts(resp.Mounts), nil
   111  }
   112  
   113  func (p *proxySnapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) {
   114  	var local snapshots.Info
   115  	for _, opt := range opts {
   116  		if err := opt(&local); err != nil {
   117  			return nil, err
   118  		}
   119  	}
   120  	resp, err := p.client.View(ctx, &snapshotsapi.ViewSnapshotRequest{
   121  		Snapshotter: p.snapshotterName,
   122  		Key:         key,
   123  		Parent:      parent,
   124  		Labels:      local.Labels,
   125  	})
   126  	if err != nil {
   127  		return nil, errdefs.FromGRPC(err)
   128  	}
   129  	return toMounts(resp.Mounts), nil
   130  }
   131  
   132  func (p *proxySnapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error {
   133  	var local snapshots.Info
   134  	for _, opt := range opts {
   135  		if err := opt(&local); err != nil {
   136  			return err
   137  		}
   138  	}
   139  	_, err := p.client.Commit(ctx, &snapshotsapi.CommitSnapshotRequest{
   140  		Snapshotter: p.snapshotterName,
   141  		Name:        name,
   142  		Key:         key,
   143  		Labels:      local.Labels,
   144  	})
   145  	return errdefs.FromGRPC(err)
   146  }
   147  
   148  func (p *proxySnapshotter) Remove(ctx context.Context, key string) error {
   149  	_, err := p.client.Remove(ctx, &snapshotsapi.RemoveSnapshotRequest{
   150  		Snapshotter: p.snapshotterName,
   151  		Key:         key,
   152  	})
   153  	return errdefs.FromGRPC(err)
   154  }
   155  
   156  func (p *proxySnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error {
   157  	sc, err := p.client.List(ctx, &snapshotsapi.ListSnapshotsRequest{
   158  		Snapshotter: p.snapshotterName,
   159  		Filters:     fs,
   160  	})
   161  	if err != nil {
   162  		return errdefs.FromGRPC(err)
   163  	}
   164  	for {
   165  		resp, err := sc.Recv()
   166  		if err != nil {
   167  			if err == io.EOF {
   168  				return nil
   169  			}
   170  			return errdefs.FromGRPC(err)
   171  		}
   172  		if resp == nil {
   173  			return nil
   174  		}
   175  		for _, info := range resp.Info {
   176  			if err := fn(ctx, toInfo(info)); err != nil {
   177  				return err
   178  			}
   179  		}
   180  	}
   181  }
   182  
   183  func (p *proxySnapshotter) Close() error {
   184  	return nil
   185  }
   186  
   187  func (p *proxySnapshotter) Cleanup(ctx context.Context) error {
   188  	_, err := p.client.Cleanup(ctx, &snapshotsapi.CleanupRequest{
   189  		Snapshotter: p.snapshotterName,
   190  	})
   191  	return errdefs.FromGRPC(err)
   192  }
   193  
   194  func toKind(kind snapshotsapi.Kind) snapshots.Kind {
   195  	if kind == snapshotsapi.KindActive {
   196  		return snapshots.KindActive
   197  	}
   198  	if kind == snapshotsapi.KindView {
   199  		return snapshots.KindView
   200  	}
   201  	return snapshots.KindCommitted
   202  }
   203  
   204  func toInfo(info snapshotsapi.Info) snapshots.Info {
   205  	return snapshots.Info{
   206  		Name:    info.Name,
   207  		Parent:  info.Parent,
   208  		Kind:    toKind(info.Kind),
   209  		Created: info.CreatedAt,
   210  		Updated: info.UpdatedAt,
   211  		Labels:  info.Labels,
   212  	}
   213  }
   214  
   215  func toUsage(resp *snapshotsapi.UsageResponse) snapshots.Usage {
   216  	return snapshots.Usage{
   217  		Inodes: resp.Inodes,
   218  		Size:   resp.Size_,
   219  	}
   220  }
   221  
   222  func toMounts(mm []*types.Mount) []mount.Mount {
   223  	mounts := make([]mount.Mount, len(mm))
   224  	for i, m := range mm {
   225  		mounts[i] = mount.Mount{
   226  			Type:    m.Type,
   227  			Source:  m.Source,
   228  			Options: m.Options,
   229  		}
   230  	}
   231  	return mounts
   232  }
   233  
   234  func fromKind(kind snapshots.Kind) snapshotsapi.Kind {
   235  	if kind == snapshots.KindActive {
   236  		return snapshotsapi.KindActive
   237  	}
   238  	if kind == snapshots.KindView {
   239  		return snapshotsapi.KindView
   240  	}
   241  	return snapshotsapi.KindCommitted
   242  }
   243  
   244  func fromInfo(info snapshots.Info) snapshotsapi.Info {
   245  	return snapshotsapi.Info{
   246  		Name:      info.Name,
   247  		Parent:    info.Parent,
   248  		Kind:      fromKind(info.Kind),
   249  		CreatedAt: info.Created,
   250  		UpdatedAt: info.Updated,
   251  		Labels:    info.Labels,
   252  	}
   253  }