mesh/delivery-group group feat/774-l3-reland rejected: composed together: the checker's verdict at the members' heads (b48c90fea31f): integration: mesh-self-ch…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed: integration: mesh-self-check/cmd/mesh-self-check.TestTheSelfCheckWholeRunsOnTheBus: the run answered {Run:doctor-1793351737-1 At:20…
One commit with exactly the tree of the reviewed head35b4509c0a, on main12c2574c9d, so two compiled programs added and removed on the branch leave no trace in history (issue 1577).
58 lines
2.0 KiB
Go
58 lines
2.0 KiB
Go
package registry
|
|
|
|
import (
|
|
"context"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
// blobBound is the most GetBlob reads: a templates archive is a few kilobytes; anything near this is no archive a
|
|
// take-in reads text from.
|
|
const blobBound = 64 << 20
|
|
|
|
// GetBlob is the archive a recorded reference names (`artifact-store://<repository>/blobs/sha256:<hex>`), read whole
|
|
// and checked against the digest it names: bytes that hash to another digest are refused, never read (R4e: the
|
|
// controller reads a templates archive by the reference of a builder's done key). Gone when the store does not hold
|
|
// it; ErrNotOurs for a reference outside the store or one that is not an archive.
|
|
func (s Store) GetBlob(ctx context.Context, reference string) ([]byte, error) {
|
|
repository, digest, archive, err := s.archive(reference)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !archive {
|
|
return nil, fmt.Errorf("%w: %s is not an archive", ErrNotOurs, reference)
|
|
}
|
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, s.url(repository, "blobs", digest), nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
response, err := s.client().Do(request)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("cannot reach the artifact store at %s: %w", s.Address, err)
|
|
}
|
|
defer response.Body.Close()
|
|
switch response.StatusCode {
|
|
case http.StatusOK:
|
|
case http.StatusNotFound:
|
|
return nil, Gone
|
|
default:
|
|
return nil, fmt.Errorf("the artifact store answered %s for %s/blobs/%s", response.Status, repository, digest)
|
|
}
|
|
body, err := io.ReadAll(io.LimitReader(response.Body, blobBound+1))
|
|
if err != nil {
|
|
return nil, fmt.Errorf("reading %s/blobs/%s: %w", repository, digest, err)
|
|
}
|
|
if len(body) > blobBound {
|
|
return nil, fmt.Errorf("%s/blobs/%s is larger than %d bytes, which no archive read here is", repository, digest, blobBound)
|
|
}
|
|
sum := sha256.Sum256(body)
|
|
if got := "sha256:" + hex.EncodeToString(sum[:]); got != digest {
|
|
return nil, fmt.Errorf("the artifact store answered %s/blobs/%s with bytes of the digest %s: refused", repository,
|
|
digest, got)
|
|
}
|
|
return body, nil
|
|
}
|