MCPcopy Create free account
hub / github.com/containers/image / PutBlobWithOptions

Method PutBlobWithOptions

docker/docker_image_dest.go:138–228  ·  view source on GitHub ↗

PutBlobWithOptions writes contents of stream and returns data representing the result. inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents. inputInfo.Size is the expected length of stream, if known.

(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, options private.PutBlobOptions)

Source from the content-addressed store, hash-verified

136// to any other readers for download using the supplied digest.
137// If stream.Read() at any time, ESPECIALLY at end of input, returns an error, PutBlobWithOptions MUST 1) fail, and 2) delete any data stored so far.
138func (d *dockerImageDestination) PutBlobWithOptions(ctx context.Context, stream io.Reader, inputInfo types.BlobInfo, options private.PutBlobOptions) (private.UploadedBlob, error) {
139 // If requested, precompute the blob digest to prevent uploading layers that already exist on the registry.
140 // This functionality is particularly useful when BlobInfoCache has not been populated with compressed digests,
141 // the source blob is uncompressed, and the destination blob is being compressed "on the fly".
142 if inputInfo.Digest == "" && d.c.sys != nil && d.c.sys.DockerRegistryPushPrecomputeDigests {
143 logrus.Debugf("Precomputing digest layer for %s", reference.Path(d.ref.ref))
144 streamCopy, cleanup, err := streamdigest.ComputeBlobInfo(d.c.sys, stream, &inputInfo)
145 if err != nil {
146 return private.UploadedBlob{}, err
147 }
148 defer cleanup()
149 stream = streamCopy
150 }
151
152 if inputInfo.Digest != "" {
153 // This should not really be necessary, at least the copy code calls TryReusingBlob automatically.
154 // Still, we need to check, if only because the "initiate upload" endpoint does not have a documented "blob already exists" return value.
155 haveBlob, reusedInfo, err := d.tryReusingExactBlob(ctx, inputInfo, options.Cache)
156 if err != nil {
157 return private.UploadedBlob{}, err
158 }
159 if haveBlob {
160 return private.UploadedBlob{Digest: reusedInfo.Digest, Size: reusedInfo.Size}, nil
161 }
162 }
163
164 // FIXME? Chunked upload, progress reporting, etc.
165 uploadPath := fmt.Sprintf(blobUploadPath, reference.Path(d.ref.ref))
166 logrus.Debugf("Uploading %s", uploadPath)
167 res, err := d.c.makeRequest(ctx, http.MethodPost, uploadPath, nil, nil, v2Auth, nil)
168 if err != nil {
169 return private.UploadedBlob{}, err
170 }
171 defer res.Body.Close()
172 if res.StatusCode != http.StatusAccepted {
173 logrus.Debugf("Error initiating layer upload, response %#v", *res)
174 return private.UploadedBlob{}, fmt.Errorf("initiating layer upload to %s in %s: %w", uploadPath, d.c.registry, registryHTTPResponseToError(res))
175 }
176 uploadLocation, err := res.Location()
177 if err != nil {
178 return private.UploadedBlob{}, fmt.Errorf("determining upload URL: %w", err)
179 }
180
181 digester, stream := putblobdigest.DigestIfCanonicalUnknown(stream, inputInfo)
182 sizeCounter := &sizeCounter{}
183 stream = io.TeeReader(stream, sizeCounter)
184
185 uploadLocation, err = func() (*url.URL, error) { // A scope for defer
186 uploadReader := uploadreader.NewUploadReader(stream)
187 // This error text should never be user-visible, we terminate only after makeRequestToResolvedURL
188 // returns, so there isn’t a way for the error text to be provided to any of our callers.
189 defer uploadReader.Terminate(errors.New("Reading data from an already terminated upload"))
190 res, err = d.c.makeRequestToResolvedURL(ctx, http.MethodPatch, uploadLocation, map[string][]string{"Content-Type": {"application/octet-stream"}}, uploadReader, inputInfo.Size, v2Auth, nil)
191 if err != nil {
192 logrus.Debugf("Error uploading layer chunked %v", err)
193 return nil, err
194 }
195 defer res.Body.Close()

Callers 1

putBlobBytesAsOCIMethod · 0.95

Calls 15

tryReusingExactBlobMethod · 0.95
TerminateMethod · 0.95
PathFunction · 0.92
ComputeBlobInfoFunction · 0.92
DigestIfCanonicalUnknownFunction · 0.92
NewUploadReaderFunction · 0.92
successStatusFunction · 0.85
bicTransportScopeFunction · 0.85
newBICLocationReferenceFunction · 0.85
CloseMethod · 0.65

Tested by

no test coverage detected