@@ -18,26 +18,49 @@ package proxy
1818
1919import (
2020 "context"
21+ "fmt"
2122 "io"
2223
2324 contentapi "github.com/containerd/containerd/v2/api/services/content/v1"
2425 "github.com/containerd/containerd/v2/core/content"
2526 "github.com/containerd/containerd/v2/protobuf"
2627 protobuftypes "github.com/containerd/containerd/v2/protobuf/types"
2728 "github.com/containerd/errdefs"
29+ "github.com/containerd/ttrpc"
2830 digest "github.com/opencontainers/go-digest"
2931 ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32+ "google.golang.org/grpc"
33+ "google.golang.org/protobuf/types/known/emptypb"
3034)
3135
3236type 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
3440}
3541
3642// NewContentStore returns a new content store which communicates over a GRPC
3743// 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 ))
4164 }
4265}
4366
@@ -191,7 +214,7 @@ func (pcs *proxyContentStore) Abort(ctx context.Context, ref string) error {
191214 return nil
192215}
193216
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 ) {
195218 wrclient , err := pcs .client .Write (ctx )
196219 if err != nil {
197220 return nil , 0 , err
@@ -214,6 +237,70 @@ func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size in
214237 return wrclient , resp .Offset , nil
215238}
216239
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+
217304func infoToGRPC (info * content.Info ) * contentapi.Info {
218305 return & contentapi.Info {
219306 Digest : info .Digest .String (),
0 commit comments