123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- 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
- }
- // BlobEnumerator enables iterating over blobs from storage
- type BlobEnumerator interface {
- Enumerate(ctx context.Context, ingester func(dgst digest.Digest) error) 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.WriteCloser
- io.ReaderFrom
- // Size returns the number of bytes written to this blob.
- Size() int64
- // 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
- }
- // 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
- }
|