github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/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 }