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