| package contentutil |
| |
| import ( |
| "context" |
| |
| "github.com/containerd/containerd/content" |
| "github.com/containerd/containerd/errdefs" |
| "github.com/containerd/containerd/remotes" |
| "github.com/pkg/errors" |
| ) |
| |
| func FromPusher(p remotes.Pusher) content.Ingester { |
| return &pushingIngester{ |
| p: p, |
| } |
| } |
| |
| type pushingIngester struct { |
| p remotes.Pusher |
| } |
| |
| // Writer implements content.Ingester. desc.MediaType must be set for manifest blobs. |
| func (i *pushingIngester) Writer(ctx context.Context, opts ...content.WriterOpt) (content.Writer, error) { |
| var wOpts content.WriterOpts |
| for _, opt := range opts { |
| if err := opt(&wOpts); err != nil { |
| return nil, err |
| } |
| } |
| if wOpts.Ref == "" { |
| return nil, errors.Wrap(errdefs.ErrInvalidArgument, "ref must not be empty") |
| } |
| // pusher requires desc.MediaType to determine the PUT URL, especially for manifest blobs. |
| contentWriter, err := i.p.Push(ctx, wOpts.Desc) |
| if err != nil { |
| return nil, err |
| } |
| return &writer{ |
| Writer: contentWriter, |
| contentWriterRef: wOpts.Ref, |
| }, nil |
| } |
| |
| type writer struct { |
| content.Writer // returned from pusher.Push |
| contentWriterRef string // ref passed for Writer() |
| } |
| |
| func (w *writer) Status() (content.Status, error) { |
| st, err := w.Writer.Status() |
| if err != nil { |
| return st, err |
| } |
| if w.contentWriterRef != "" { |
| st.Ref = w.contentWriterRef |
| } |
| return st, nil |
| } |