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