github.com/demonoid81/containerd@v1.3.4/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 func(context.Context, snapshots.Info) error) error { 157 sc, err := p.client.List(ctx, &snapshotsapi.ListSnapshotsRequest{ 158 Snapshotter: p.snapshotterName, 159 }) 160 if err != nil { 161 return errdefs.FromGRPC(err) 162 } 163 for { 164 resp, err := sc.Recv() 165 if err != nil { 166 if err == io.EOF { 167 return nil 168 } 169 return errdefs.FromGRPC(err) 170 } 171 if resp == nil { 172 return nil 173 } 174 for _, info := range resp.Info { 175 if err := fn(ctx, toInfo(info)); err != nil { 176 return err 177 } 178 } 179 } 180 } 181 182 func (p *proxySnapshotter) Close() error { 183 return nil 184 } 185 186 func toKind(kind snapshotsapi.Kind) snapshots.Kind { 187 if kind == snapshotsapi.KindActive { 188 return snapshots.KindActive 189 } 190 if kind == snapshotsapi.KindView { 191 return snapshots.KindView 192 } 193 return snapshots.KindCommitted 194 } 195 196 func toInfo(info snapshotsapi.Info) snapshots.Info { 197 return snapshots.Info{ 198 Name: info.Name, 199 Parent: info.Parent, 200 Kind: toKind(info.Kind), 201 Created: info.CreatedAt, 202 Updated: info.UpdatedAt, 203 Labels: info.Labels, 204 } 205 } 206 207 func toUsage(resp *snapshotsapi.UsageResponse) snapshots.Usage { 208 return snapshots.Usage{ 209 Inodes: resp.Inodes, 210 Size: resp.Size_, 211 } 212 } 213 214 func toMounts(mm []*types.Mount) []mount.Mount { 215 mounts := make([]mount.Mount, len(mm)) 216 for i, m := range mm { 217 mounts[i] = mount.Mount{ 218 Type: m.Type, 219 Source: m.Source, 220 Options: m.Options, 221 } 222 } 223 return mounts 224 } 225 226 func fromKind(kind snapshots.Kind) snapshotsapi.Kind { 227 if kind == snapshots.KindActive { 228 return snapshotsapi.KindActive 229 } 230 if kind == snapshots.KindView { 231 return snapshotsapi.KindView 232 } 233 return snapshotsapi.KindCommitted 234 } 235 236 func fromInfo(info snapshots.Info) snapshotsapi.Info { 237 return snapshotsapi.Info{ 238 Name: info.Name, 239 Parent: info.Parent, 240 Kind: fromKind(info.Kind), 241 CreatedAt: info.Created, 242 UpdatedAt: info.Updated, 243 Labels: info.Labels, 244 } 245 }