234 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Go
		
	
	
| package distribution
 | |
| 
 | |
| import (
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"net/http"
 | |
| 	"time"
 | |
| 
 | |
| 	"github.com/docker/distribution/context"
 | |
| 	"github.com/docker/distribution/digest"
 | |
| 	"github.com/docker/distribution/reference"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	// ErrBlobExists returned when blob already exists
 | |
| 	ErrBlobExists = errors.New("blob exists")
 | |
| 
 | |
| 	// ErrBlobDigestUnsupported when blob digest is an unsupported version.
 | |
| 	ErrBlobDigestUnsupported = errors.New("unsupported blob digest")
 | |
| 
 | |
| 	// ErrBlobUnknown when blob is not found.
 | |
| 	ErrBlobUnknown = errors.New("unknown blob")
 | |
| 
 | |
| 	// ErrBlobUploadUnknown returned when upload is not found.
 | |
| 	ErrBlobUploadUnknown = errors.New("blob upload unknown")
 | |
| 
 | |
| 	// ErrBlobInvalidLength returned when the blob has an expected length on
 | |
| 	// commit, meaning mismatched with the descriptor or an invalid value.
 | |
| 	ErrBlobInvalidLength = errors.New("blob invalid length")
 | |
| )
 | |
| 
 | |
| // ErrBlobInvalidDigest returned when digest check fails.
 | |
| type ErrBlobInvalidDigest struct {
 | |
| 	Digest digest.Digest
 | |
| 	Reason error
 | |
| }
 | |
| 
 | |
| func (err ErrBlobInvalidDigest) Error() string {
 | |
| 	return fmt.Sprintf("invalid digest for referenced layer: %v, %v",
 | |
| 		err.Digest, err.Reason)
 | |
| }
 | |
| 
 | |
| // ErrBlobMounted returned when a blob is mounted from another repository
 | |
| // instead of initiating an upload session.
 | |
| type ErrBlobMounted struct {
 | |
| 	From       reference.Canonical
 | |
| 	Descriptor Descriptor
 | |
| }
 | |
| 
 | |
| func (err ErrBlobMounted) Error() string {
 | |
| 	return fmt.Sprintf("blob mounted from: %v to: %v",
 | |
| 		err.From, err.Descriptor)
 | |
| }
 | |
| 
 | |
| // Descriptor describes targeted content. Used in conjunction with a blob
 | |
| // store, a descriptor can be used to fetch, store and target any kind of
 | |
| // blob. The struct also describes the wire protocol format. Fields should
 | |
| // only be added but never changed.
 | |
| type Descriptor struct {
 | |
| 	// MediaType describe the type of the content. All text based formats are
 | |
| 	// encoded as utf-8.
 | |
| 	MediaType string `json:"mediaType,omitempty"`
 | |
| 
 | |
| 	// Size in bytes of content.
 | |
| 	Size int64 `json:"size,omitempty"`
 | |
| 
 | |
| 	// Digest uniquely identifies the content. A byte stream can be verified
 | |
| 	// against against this digest.
 | |
| 	Digest digest.Digest `json:"digest,omitempty"`
 | |
| 
 | |
| 	// NOTE: Before adding a field here, please ensure that all
 | |
| 	// other options have been exhausted. Much of the type relationships
 | |
| 	// depend on the simplicity of this type.
 | |
| }
 | |
| 
 | |
| // Descriptor returns the descriptor, to make it satisfy the Describable
 | |
| // interface. Note that implementations of Describable are generally objects
 | |
| // which can be described, not simply descriptors; this exception is in place
 | |
| // to make it more convenient to pass actual descriptors to functions that
 | |
| // expect Describable objects.
 | |
| func (d Descriptor) Descriptor() Descriptor {
 | |
| 	return d
 | |
| }
 | |
| 
 | |
| // BlobStatter makes blob descriptors available by digest. The service may
 | |
| // provide a descriptor of a different digest if the provided digest is not
 | |
| // canonical.
 | |
| type BlobStatter interface {
 | |
| 	// Stat provides metadata about a blob identified by the digest. If the
 | |
| 	// blob is unknown to the describer, ErrBlobUnknown will be returned.
 | |
| 	Stat(ctx context.Context, dgst digest.Digest) (Descriptor, error)
 | |
| }
 | |
| 
 | |
| // BlobDeleter enables deleting blobs from storage.
 | |
| type BlobDeleter interface {
 | |
| 	Delete(ctx context.Context, dgst digest.Digest) error
 | |
| }
 | |
| 
 | |
| // BlobDescriptorService manages metadata about a blob by digest. Most
 | |
| // implementations will not expose such an interface explicitly. Such mappings
 | |
| // should be maintained by interacting with the BlobIngester. Hence, this is
 | |
| // left off of BlobService and BlobStore.
 | |
| type BlobDescriptorService interface {
 | |
| 	BlobStatter
 | |
| 
 | |
| 	// SetDescriptor assigns the descriptor to the digest. The provided digest and
 | |
| 	// the digest in the descriptor must map to identical content but they may
 | |
| 	// differ on their algorithm. The descriptor must have the canonical
 | |
| 	// digest of the content and the digest algorithm must match the
 | |
| 	// annotators canonical algorithm.
 | |
| 	//
 | |
| 	// Such a facility can be used to map blobs between digest domains, with
 | |
| 	// the restriction that the algorithm of the descriptor must match the
 | |
| 	// canonical algorithm (ie sha256) of the annotator.
 | |
| 	SetDescriptor(ctx context.Context, dgst digest.Digest, desc Descriptor) error
 | |
| 
 | |
| 	// Clear enables descriptors to be unlinked
 | |
| 	Clear(ctx context.Context, dgst digest.Digest) error
 | |
| }
 | |
| 
 | |
| // ReadSeekCloser is the primary reader type for blob data, combining
 | |
| // io.ReadSeeker with io.Closer.
 | |
| type ReadSeekCloser interface {
 | |
| 	io.ReadSeeker
 | |
| 	io.Closer
 | |
| }
 | |
| 
 | |
| // BlobProvider describes operations for getting blob data.
 | |
| type BlobProvider interface {
 | |
| 	// Get returns the entire blob identified by digest along with the descriptor.
 | |
| 	Get(ctx context.Context, dgst digest.Digest) ([]byte, error)
 | |
| 
 | |
| 	// Open provides a ReadSeekCloser to the blob identified by the provided
 | |
| 	// descriptor. If the blob is not known to the service, an error will be
 | |
| 	// returned.
 | |
| 	Open(ctx context.Context, dgst digest.Digest) (ReadSeekCloser, error)
 | |
| }
 | |
| 
 | |
| // BlobServer can serve blobs via http.
 | |
| type BlobServer interface {
 | |
| 	// ServeBlob attempts to serve the blob, identifed by dgst, via http. The
 | |
| 	// service may decide to redirect the client elsewhere or serve the data
 | |
| 	// directly.
 | |
| 	//
 | |
| 	// This handler only issues successful responses, such as 2xx or 3xx,
 | |
| 	// meaning it serves data or issues a redirect. If the blob is not
 | |
| 	// available, an error will be returned and the caller may still issue a
 | |
| 	// response.
 | |
| 	//
 | |
| 	// The implementation may serve the same blob from a different digest
 | |
| 	// domain. The appropriate headers will be set for the blob, unless they
 | |
| 	// have already been set by the caller.
 | |
| 	ServeBlob(ctx context.Context, w http.ResponseWriter, r *http.Request, dgst digest.Digest) error
 | |
| }
 | |
| 
 | |
| // BlobIngester ingests blob data.
 | |
| type BlobIngester interface {
 | |
| 	// Put inserts the content p into the blob service, returning a descriptor
 | |
| 	// or an error.
 | |
| 	Put(ctx context.Context, mediaType string, p []byte) (Descriptor, error)
 | |
| 
 | |
| 	// Create allocates a new blob writer to add a blob to this service. The
 | |
| 	// returned handle can be written to and later resumed using an opaque
 | |
| 	// identifier. With this approach, one can Close and Resume a BlobWriter
 | |
| 	// multiple times until the BlobWriter is committed or cancelled.
 | |
| 	Create(ctx context.Context, options ...BlobCreateOption) (BlobWriter, error)
 | |
| 
 | |
| 	// Resume attempts to resume a write to a blob, identified by an id.
 | |
| 	Resume(ctx context.Context, id string) (BlobWriter, error)
 | |
| }
 | |
| 
 | |
| // BlobCreateOption is a general extensible function argument for blob creation
 | |
| // methods. A BlobIngester may choose to honor any or none of the given
 | |
| // BlobCreateOptions, which can be specific to the implementation of the
 | |
| // BlobIngester receiving them.
 | |
| // TODO (brianbland): unify this with ManifestServiceOption in the future
 | |
| type BlobCreateOption interface {
 | |
| 	Apply(interface{}) error
 | |
| }
 | |
| 
 | |
| // BlobWriter provides a handle for inserting data into a blob store.
 | |
| // Instances should be obtained from BlobWriteService.Writer and
 | |
| // BlobWriteService.Resume. If supported by the store, a writer can be
 | |
| // recovered with the id.
 | |
| type BlobWriter interface {
 | |
| 	io.WriteSeeker
 | |
| 	io.ReaderFrom
 | |
| 	io.Closer
 | |
| 
 | |
| 	// ID returns the identifier for this writer. The ID can be used with the
 | |
| 	// Blob service to later resume the write.
 | |
| 	ID() string
 | |
| 
 | |
| 	// StartedAt returns the time this blob write was started.
 | |
| 	StartedAt() time.Time
 | |
| 
 | |
| 	// Commit completes the blob writer process. The content is verified
 | |
| 	// against the provided provisional descriptor, which may result in an
 | |
| 	// error. Depending on the implementation, written data may be validated
 | |
| 	// against the provisional descriptor fields. If MediaType is not present,
 | |
| 	// the implementation may reject the commit or assign "application/octet-
 | |
| 	// stream" to the blob. The returned descriptor may have a different
 | |
| 	// digest depending on the blob store, referred to as the canonical
 | |
| 	// descriptor.
 | |
| 	Commit(ctx context.Context, provisional Descriptor) (canonical Descriptor, err error)
 | |
| 
 | |
| 	// Cancel ends the blob write without storing any data and frees any
 | |
| 	// associated resources. Any data written thus far will be lost. Cancel
 | |
| 	// implementations should allow multiple calls even after a commit that
 | |
| 	// result in a no-op. This allows use of Cancel in a defer statement,
 | |
| 	// increasing the assurance that it is correctly called.
 | |
| 	Cancel(ctx context.Context) error
 | |
| 
 | |
| 	// Get a reader to the blob being written by this BlobWriter
 | |
| 	Reader() (io.ReadCloser, error)
 | |
| }
 | |
| 
 | |
| // BlobService combines the operations to access, read and write blobs. This
 | |
| // can be used to describe remote blob services.
 | |
| type BlobService interface {
 | |
| 	BlobStatter
 | |
| 	BlobProvider
 | |
| 	BlobIngester
 | |
| }
 | |
| 
 | |
| // BlobStore represent the entire suite of blob related operations. Such an
 | |
| // implementation can access, read, write, delete and serve blobs.
 | |
| type BlobStore interface {
 | |
| 	BlobService
 | |
| 	BlobServer
 | |
| 	BlobDeleter
 | |
| }
 |