@@ -18,26 +18,49 @@ package proxy
18
18
19
19
import (
20
20
"context"
21
+ "fmt"
21
22
"io"
22
23
23
24
contentapi "github.com/containerd/containerd/v2/api/services/content/v1"
24
25
"github.com/containerd/containerd/v2/core/content"
25
26
"github.com/containerd/containerd/v2/protobuf"
26
27
protobuftypes "github.com/containerd/containerd/v2/protobuf/types"
27
28
"github.com/containerd/errdefs"
29
+ "github.com/containerd/ttrpc"
28
30
digest "github.com/opencontainers/go-digest"
29
31
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32
+ "google.golang.org/grpc"
33
+ "google.golang.org/protobuf/types/known/emptypb"
30
34
)
31
35
32
36
type proxyContentStore struct {
33
- client contentapi.ContentClient
37
+ // client is the rpc content client
38
+ // NOTE: ttrpc is used because it is the smaller interface shared with grpc
39
+ client contentapi.TTRPCContentClient
34
40
}
35
41
36
42
// NewContentStore returns a new content store which communicates over a GRPC
37
43
// connection using the containerd content GRPC API.
38
- func NewContentStore (client contentapi.ContentClient ) content.Store {
39
- return & proxyContentStore {
40
- client : client ,
44
+ func NewContentStore (client any ) content.Store {
45
+ switch c := client .(type ) {
46
+ case contentapi.ContentClient :
47
+ return & proxyContentStore {
48
+ client : convertClient {c },
49
+ }
50
+ case grpc.ClientConnInterface :
51
+ return & proxyContentStore {
52
+ client : convertClient {contentapi .NewContentClient (c )},
53
+ }
54
+ case contentapi.TTRPCContentClient :
55
+ return & proxyContentStore {
56
+ client : c ,
57
+ }
58
+ case * ttrpc.Client :
59
+ return & proxyContentStore {
60
+ client : contentapi .NewTTRPCContentClient (c ),
61
+ }
62
+ default :
63
+ panic (fmt .Errorf ("unsupported content client %T: %w" , client , errdefs .ErrNotImplemented ))
41
64
}
42
65
}
43
66
@@ -191,7 +214,7 @@ func (pcs *proxyContentStore) Abort(ctx context.Context, ref string) error {
191
214
return nil
192
215
}
193
216
194
- func (pcs * proxyContentStore ) negotiate (ctx context.Context , ref string , size int64 , expected digest.Digest ) (contentapi.Content_WriteClient , int64 , error ) {
217
+ func (pcs * proxyContentStore ) negotiate (ctx context.Context , ref string , size int64 , expected digest.Digest ) (contentapi.TTRPCContent_WriteClient , int64 , error ) {
195
218
wrclient , err := pcs .client .Write (ctx )
196
219
if err != nil {
197
220
return nil , 0 , err
@@ -214,6 +237,70 @@ func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size in
214
237
return wrclient , resp .Offset , nil
215
238
}
216
239
240
+ type convertClient struct {
241
+ contentapi.ContentClient
242
+ }
243
+
244
+ func (c convertClient ) Info (ctx context.Context , req * contentapi.InfoRequest ) (* contentapi.InfoResponse , error ) {
245
+ return c .ContentClient .Info (ctx , req )
246
+ }
247
+
248
+ func (c convertClient ) Update (ctx context.Context , req * contentapi.UpdateRequest ) (* contentapi.UpdateResponse , error ) {
249
+ return c .ContentClient .Update (ctx , req )
250
+ }
251
+
252
+ type convertListClient struct {
253
+ contentapi.Content_ListClient
254
+ }
255
+
256
+ func (c convertClient ) List (ctx context.Context , req * contentapi.ListContentRequest ) (contentapi.TTRPCContent_ListClient , error ) {
257
+ lc , err := c .ContentClient .List (ctx , req )
258
+ if lc == nil {
259
+ return nil , err
260
+ }
261
+ return convertListClient {lc }, err
262
+ }
263
+
264
+ func (c convertClient ) Delete (ctx context.Context , req * contentapi.DeleteContentRequest ) (* emptypb.Empty , error ) {
265
+ return c .ContentClient .Delete (ctx , req )
266
+ }
267
+
268
+ type convertReadClient struct {
269
+ contentapi.Content_ReadClient
270
+ }
271
+
272
+ func (c convertClient ) Read (ctx context.Context , req * contentapi.ReadContentRequest ) (contentapi.TTRPCContent_ReadClient , error ) {
273
+ rc , err := c .ContentClient .Read (ctx , req )
274
+ if rc == nil {
275
+ return nil , err
276
+ }
277
+ return convertReadClient {rc }, err
278
+ }
279
+
280
+ func (c convertClient ) Status (ctx context.Context , req * contentapi.StatusRequest ) (* contentapi.StatusResponse , error ) {
281
+ return c .ContentClient .Status (ctx , req )
282
+ }
283
+
284
+ func (c convertClient ) ListStatuses (ctx context.Context , req * contentapi.ListStatusesRequest ) (* contentapi.ListStatusesResponse , error ) {
285
+ return c .ContentClient .ListStatuses (ctx , req )
286
+ }
287
+
288
+ type convertWriteClient struct {
289
+ contentapi.Content_WriteClient
290
+ }
291
+
292
+ func (c convertClient ) Write (ctx context.Context ) (contentapi.TTRPCContent_WriteClient , error ) {
293
+ wc , err := c .ContentClient .Write (ctx )
294
+ if wc == nil {
295
+ return nil , err
296
+ }
297
+ return convertWriteClient {wc }, err
298
+ }
299
+
300
+ func (c convertClient ) Abort (ctx context.Context , req * contentapi.AbortRequest ) (* emptypb.Empty , error ) {
301
+ return c .ContentClient .Abort (ctx , req )
302
+ }
303
+
217
304
func infoToGRPC (info * content.Info ) * contentapi.Info {
218
305
return & contentapi.Info {
219
306
Digest : info .Digest .String (),
0 commit comments