github.com/mika/distribution@v2.2.2-0.20160108133430-a75790e3d8e0+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  // Descriptor returns the descriptor, to make it satisfy the Describable
    65  // interface. Note that implementations of Describable are generally objects
    66  // which can be described, not simply descriptors; this exception is in place
    67  // to make it more convenient to pass actual descriptors to functions that
    68  // expect Describable objects.
    69  func (d Descriptor) Descriptor() Descriptor {
    70  	return d
    71  }
    72  
    73  // BlobStatter makes blob descriptors available by digest. The service may
    74  // provide a descriptor of a different digest if the provided digest is not
    75  // canonical.
    76  type BlobStatter interface {
    77  	// Stat provides metadata about a blob identified by the digest. If the
    78  	// blob is unknown to the describer, ErrBlobUnknown will be returned.
    79  	Stat(ctx context.Context, dgst digest.Digest) (Descriptor, error)
    80  }
    81  
    82  // BlobDeleter enables deleting blobs from storage.
    83  type BlobDeleter interface {
    84  	Delete(ctx context.Context, dgst digest.Digest) error
    85  }
    86  
    87  // BlobDescriptorService manages metadata about a blob by digest. Most
    88  // implementations will not expose such an interface explicitly. Such mappings
    89  // should be maintained by interacting with the BlobIngester. Hence, this is
    90  // left off of BlobService and BlobStore.
    91  type BlobDescriptorService interface {
    92  	BlobStatter
    93  
    94  	// SetDescriptor assigns the descriptor to the digest. The provided digest and
    95  	// the digest in the descriptor must map to identical content but they may
    96  	// differ on their algorithm. The descriptor must have the canonical
    97  	// digest of the content and the digest algorithm must match the
    98  	// annotators canonical algorithm.
    99  	//
   100  	// Such a facility can be used to map blobs between digest domains, with
   101  	// the restriction that the algorithm of the descriptor must match the
   102  	// canonical algorithm (ie sha256) of the annotator.
   103  	SetDescriptor(ctx context.Context, dgst digest.Digest, desc Descriptor) error
   104  
   105  	// Clear enables descriptors to be unlinked
   106  	Clear(ctx context.Context, dgst digest.Digest) error
   107  }
   108  
   109  // ReadSeekCloser is the primary reader type for blob data, combining
   110  // io.ReadSeeker with io.Closer.
   111  type ReadSeekCloser interface {
   112  	io.ReadSeeker
   113  	io.Closer
   114  }
   115  
   116  // BlobProvider describes operations for getting blob data.
   117  type BlobProvider interface {
   118  	// Get returns the entire blob identified by digest along with the descriptor.
   119  	Get(ctx context.Context, dgst digest.Digest) ([]byte, error)
   120  
   121  	// Open provides a ReadSeekCloser to the blob identified by the provided
   122  	// descriptor. If the blob is not known to the service, an error will be
   123  	// returned.
   124  	Open(ctx context.Context, dgst digest.Digest) (ReadSeekCloser, error)
   125  }
   126  
   127  // BlobServer can serve blobs via http.
   128  type BlobServer interface {
   129  	// ServeBlob attempts to serve the blob, identifed by dgst, via http. The
   130  	// service may decide to redirect the client elsewhere or serve the data
   131  	// directly.
   132  	//
   133  	// This handler only issues successful responses, such as 2xx or 3xx,
   134  	// meaning it serves data or issues a redirect. If the blob is not
   135  	// available, an error will be returned and the caller may still issue a
   136  	// response.
   137  	//
   138  	// The implementation may serve the same blob from a different digest
   139  	// domain. The appropriate headers will be set for the blob, unless they
   140  	// have already been set by the caller.
   141  	ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error
   142  }
   143  
   144  // BlobIngester ingests blob data.
   145  type BlobIngester interface {
   146  	// Put inserts the content p into the blob service, returning a descriptor
   147  	// or an error.
   148  	Put(ctx context.Context, mediaType string, p []byte) (Descriptor, error)
   149  
   150  	// Create allocates a new blob writer to add a blob to this service. The
   151  	// returned handle can be written to and later resumed using an opaque
   152  	// identifier. With this approach, one can Close and Resume a BlobWriter
   153  	// multiple times until the BlobWriter is committed or cancelled.
   154  	Create(ctx context.Context) (BlobWriter, error)
   155  
   156  	// Resume attempts to resume a write to a blob, identified by an id.
   157  	Resume(ctx context.Context, id string) (BlobWriter, error)
   158  }
   159  
   160  // BlobWriter provides a handle for inserting data into a blob store.
   161  // Instances should be obtained from BlobWriteService.Writer and
   162  // BlobWriteService.Resume. If supported by the store, a writer can be
   163  // recovered with the id.
   164  type BlobWriter interface {
   165  	io.WriteSeeker
   166  	io.ReaderFrom
   167  	io.Closer
   168  
   169  	// ID returns the identifier for this writer. The ID can be used with the
   170  	// Blob service to later resume the write.
   171  	ID() string
   172  
   173  	// StartedAt returns the time this blob write was started.
   174  	StartedAt() time.Time
   175  
   176  	// Commit completes the blob writer process. The content is verified
   177  	// against the provided provisional descriptor, which may result in an
   178  	// error. Depending on the implementation, written data may be validated
   179  	// against the provisional descriptor fields. If MediaType is not present,
   180  	// the implementation may reject the commit or assign "application/octet-
   181  	// stream" to the blob. The returned descriptor may have a different
   182  	// digest depending on the blob store, referred to as the canonical
   183  	// descriptor.
   184  	Commit(ctx context.Context, provisional Descriptor) (canonical Descriptor, err error)
   185  
   186  	// Cancel ends the blob write without storing any data and frees any
   187  	// associated resources. Any data written thus far will be lost. Cancel
   188  	// implementations should allow multiple calls even after a commit that
   189  	// result in a no-op. This allows use of Cancel in a defer statement,
   190  	// increasing the assurance that it is correctly called.
   191  	Cancel(ctx context.Context) error
   192  
   193  	// Get a reader to the blob being written by this BlobWriter
   194  	Reader() (io.ReadCloser, error)
   195  }
   196  
   197  // BlobService combines the operations to access, read and write blobs. This
   198  // can be used to describe remote blob services.
   199  type BlobService interface {
   200  	BlobStatter
   201  	BlobProvider
   202  	BlobIngester
   203  }
   204  
   205  // BlobStore represent the entire suite of blob related operations. Such an
   206  // implementation can access, read, write, delete and serve blobs.
   207  type BlobStore interface {
   208  	BlobService
   209  	BlobServer
   210  	BlobDeleter
   211  }