github.com/npaton/distribution@v2.3.1-rc.0+incompatible/blobs.go (about)

     1  package distribution
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"time"
     9  
    10  	"github.com/docker/distribution/context"
    11  	"github.com/docker/distribution/digest"
    12  	"github.com/docker/distribution/reference"
    13  )
    14  
    15  var (
    16  	// ErrBlobExists returned when blob already exists
    17  	ErrBlobExists = errors.New("blob exists")
    18  
    19  	// ErrBlobDigestUnsupported when blob digest is an unsupported version.
    20  	ErrBlobDigestUnsupported = errors.New("unsupported blob digest")
    21  
    22  	// ErrBlobUnknown when blob is not found.
    23  	ErrBlobUnknown = errors.New("unknown blob")
    24  
    25  	// ErrBlobUploadUnknown returned when upload is not found.
    26  	ErrBlobUploadUnknown = errors.New("blob upload unknown")
    27  
    28  	// ErrBlobInvalidLength returned when the blob has an expected length on
    29  	// commit, meaning mismatched with the descriptor or an invalid value.
    30  	ErrBlobInvalidLength = errors.New("blob invalid length")
    31  )
    32  
    33  // ErrBlobInvalidDigest returned when digest check fails.
    34  type ErrBlobInvalidDigest struct {
    35  	Digest digest.Digest
    36  	Reason error
    37  }
    38  
    39  func (err ErrBlobInvalidDigest) Error() string {
    40  	return fmt.Sprintf("invalid digest for referenced layer: %v, %v",
    41  		err.Digest, err.Reason)
    42  }
    43  
    44  // ErrBlobMounted returned when a blob is mounted from another repository
    45  // instead of initiating an upload session.
    46  type ErrBlobMounted struct {
    47  	From       reference.Canonical
    48  	Descriptor Descriptor
    49  }
    50  
    51  func (err ErrBlobMounted) Error() string {
    52  	return fmt.Sprintf("blob mounted from: %v to: %v",
    53  		err.From, err.Descriptor)
    54  }
    55  
    56  // Descriptor describes targeted content. Used in conjunction with a blob
    57  // store, a descriptor can be used to fetch, store and target any kind of
    58  // blob. The struct also describes the wire protocol format. Fields should
    59  // only be added but never changed.
    60  type Descriptor struct {
    61  	// MediaType describe the type of the content. All text based formats are
    62  	// encoded as utf-8.
    63  	MediaType string `json:"mediaType,omitempty"`
    64  
    65  	// Size in bytes of content.
    66  	Size int64 `json:"size,omitempty"`
    67  
    68  	// Digest uniquely identifies the content. A byte stream can be verified
    69  	// against against this digest.
    70  	Digest digest.Digest `json:"digest,omitempty"`
    71  
    72  	// NOTE: Before adding a field here, please ensure that all
    73  	// other options have been exhausted. Much of the type relationships
    74  	// depend on the simplicity of this type.
    75  }
    76  
    77  // Descriptor returns the descriptor, to make it satisfy the Describable
    78  // interface. Note that implementations of Describable are generally objects
    79  // which can be described, not simply descriptors; this exception is in place
    80  // to make it more convenient to pass actual descriptors to functions that
    81  // expect Describable objects.
    82  func (d Descriptor) Descriptor() Descriptor {
    83  	return d
    84  }
    85  
    86  // BlobStatter makes blob descriptors available by digest. The service may
    87  // provide a descriptor of a different digest if the provided digest is not
    88  // canonical.
    89  type BlobStatter interface {
    90  	// Stat provides metadata about a blob identified by the digest. If the
    91  	// blob is unknown to the describer, ErrBlobUnknown will be returned.
    92  	Stat(ctx context.Context, dgst digest.Digest) (Descriptor, error)
    93  }
    94  
    95  // BlobDeleter enables deleting blobs from storage.
    96  type BlobDeleter interface {
    97  	Delete(ctx context.Context, dgst digest.Digest) error
    98  }
    99  
   100  // BlobDescriptorService manages metadata about a blob by digest. Most
   101  // implementations will not expose such an interface explicitly. Such mappings
   102  // should be maintained by interacting with the BlobIngester. Hence, this is
   103  // left off of BlobService and BlobStore.
   104  type BlobDescriptorService interface {
   105  	BlobStatter
   106  
   107  	// SetDescriptor assigns the descriptor to the digest. The provided digest and
   108  	// the digest in the descriptor must map to identical content but they may
   109  	// differ on their algorithm. The descriptor must have the canonical
   110  	// digest of the content and the digest algorithm must match the
   111  	// annotators canonical algorithm.
   112  	//
   113  	// Such a facility can be used to map blobs between digest domains, with
   114  	// the restriction that the algorithm of the descriptor must match the
   115  	// canonical algorithm (ie sha256) of the annotator.
   116  	SetDescriptor(ctx context.Context, dgst digest.Digest, desc Descriptor) error
   117  
   118  	// Clear enables descriptors to be unlinked
   119  	Clear(ctx context.Context, dgst digest.Digest) error
   120  }
   121  
   122  // ReadSeekCloser is the primary reader type for blob data, combining
   123  // io.ReadSeeker with io.Closer.
   124  type ReadSeekCloser interface {
   125  	io.ReadSeeker
   126  	io.Closer
   127  }
   128  
   129  // BlobProvider describes operations for getting blob data.
   130  type BlobProvider interface {
   131  	// Get returns the entire blob identified by digest along with the descriptor.
   132  	Get(ctx context.Context, dgst digest.Digest) ([]byte, error)
   133  
   134  	// Open provides a ReadSeekCloser to the blob identified by the provided
   135  	// descriptor. If the blob is not known to the service, an error will be
   136  	// returned.
   137  	Open(ctx context.Context, dgst digest.Digest) (ReadSeekCloser, error)
   138  }
   139  
   140  // BlobServer can serve blobs via http.
   141  type BlobServer interface {
   142  	// ServeBlob attempts to serve the blob, identifed by dgst, via http. The
   143  	// service may decide to redirect the client elsewhere or serve the data
   144  	// directly.
   145  	//
   146  	// This handler only issues successful responses, such as 2xx or 3xx,
   147  	// meaning it serves data or issues a redirect. If the blob is not
   148  	// available, an error will be returned and the caller may still issue a
   149  	// response.
   150  	//
   151  	// The implementation may serve the same blob from a different digest
   152  	// domain. The appropriate headers will be set for the blob, unless they
   153  	// have already been set by the caller.
   154  	ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error
   155  }
   156  
   157  // BlobIngester ingests blob data.
   158  type BlobIngester interface {
   159  	// Put inserts the content p into the blob service, returning a descriptor
   160  	// or an error.
   161  	Put(ctx context.Context, mediaType string, p []byte) (Descriptor, error)
   162  
   163  	// Create allocates a new blob writer to add a blob to this service. The
   164  	// returned handle can be written to and later resumed using an opaque
   165  	// identifier. With this approach, one can Close and Resume a BlobWriter
   166  	// multiple times until the BlobWriter is committed or cancelled.
   167  	Create(ctx context.Context, options ...BlobCreateOption) (BlobWriter, error)
   168  
   169  	// Resume attempts to resume a write to a blob, identified by an id.
   170  	Resume(ctx context.Context, id string) (BlobWriter, error)
   171  }
   172  
   173  // BlobCreateOption is a general extensible function argument for blob creation
   174  // methods. A BlobIngester may choose to honor any or none of the given
   175  // BlobCreateOptions, which can be specific to the implementation of the
   176  // BlobIngester receiving them.
   177  // TODO (brianbland): unify this with ManifestServiceOption in the future
   178  type BlobCreateOption interface {
   179  	Apply(interface{}) error
   180  }
   181  
   182  // BlobWriter provides a handle for inserting data into a blob store.
   183  // Instances should be obtained from BlobWriteService.Writer and
   184  // BlobWriteService.Resume. If supported by the store, a writer can be
   185  // recovered with the id.
   186  type BlobWriter interface {
   187  	io.WriteSeeker
   188  	io.ReaderFrom
   189  	io.Closer
   190  
   191  	// ID returns the identifier for this writer. The ID can be used with the
   192  	// Blob service to later resume the write.
   193  	ID() string
   194  
   195  	// StartedAt returns the time this blob write was started.
   196  	StartedAt() time.Time
   197  
   198  	// Commit completes the blob writer process. The content is verified
   199  	// against the provided provisional descriptor, which may result in an
   200  	// error. Depending on the implementation, written data may be validated
   201  	// against the provisional descriptor fields. If MediaType is not present,
   202  	// the implementation may reject the commit or assign "application/octet-
   203  	// stream" to the blob. The returned descriptor may have a different
   204  	// digest depending on the blob store, referred to as the canonical
   205  	// descriptor.
   206  	Commit(ctx context.Context, provisional Descriptor) (canonical Descriptor, err error)
   207  
   208  	// Cancel ends the blob write without storing any data and frees any
   209  	// associated resources. Any data written thus far will be lost. Cancel
   210  	// implementations should allow multiple calls even after a commit that
   211  	// result in a no-op. This allows use of Cancel in a defer statement,
   212  	// increasing the assurance that it is correctly called.
   213  	Cancel(ctx context.Context) error
   214  
   215  	// Get a reader to the blob being written by this BlobWriter
   216  	Reader() (io.ReadCloser, error)
   217  }
   218  
   219  // BlobService combines the operations to access, read and write blobs. This
   220  // can be used to describe remote blob services.
   221  type BlobService interface {
   222  	BlobStatter
   223  	BlobProvider
   224  	BlobIngester
   225  }
   226  
   227  // BlobStore represent the entire suite of blob related operations. Such an
   228  // implementation can access, read, write, delete and serve blobs.
   229  type BlobStore interface {
   230  	BlobService
   231  	BlobServer
   232  	BlobDeleter
   233  }