blobs.go 9.7 KB

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