Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion http/fetch/archive_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ type Option func(a *ArchiveFetcher)
// ErrFileNotFound is an error type used to signal 404 HTTP status code responses.
var ErrFileNotFound = errors.New("file not found")

// ErrDigestMismatch is an error type used to signal that the downloaded content
// doesn't match the expected digest, e.g. because the artifact changed between
// reading the source status and downloading it.
var ErrDigestMismatch = errors.New("computed digest doesn't match")

// WithRetries sets the maximum amount of retries the HTTP client will be allowed to make.
func WithRetries(retries int) Option {
return func(a *ArchiveFetcher) {
Expand Down Expand Up @@ -263,6 +268,7 @@ func (r *ArchiveFetcher) copyResponse(dst io.Writer, resp *http.Response) error
// FetchWithContext downloads, verifies and extracts the tarball content to the specified directory.
// If the file server responds with 5xx errors, the download operation is retried.
// If the file server responds with 404, the returned error is of type ErrFileNotFound.
// If the digest of the downloaded content doesn't match, the returned error wraps ErrDigestMismatch.
// If the file server is unavailable for more than 3 minutes, the returned error contains the original status code.
func (r *ArchiveFetcher) FetchWithContext(ctx context.Context, archiveURL, digest, dir string) (err error) {
resp, err := r.download(ctx, archiveURL)
Expand Down Expand Up @@ -360,7 +366,7 @@ func (r *ArchiveFetcher) verifyDigest(dig string, reader io.Reader) error {
return err
}
if !verifier.Verified() {
return fmt.Errorf("computed digest doesn't match provided '%s' (check whether file size exceeds max download size)", dig)
return fmt.Errorf("%w provided '%s'", ErrDigestMismatch, dig)
}
return nil
}
33 changes: 26 additions & 7 deletions http/fetch/archive_fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"net/http"
"os"
Expand Down Expand Up @@ -140,6 +141,7 @@ func TestArchiveFetcher_FetchWithContext(t *testing.T) {
fetchedContentPath: filepath.Join(tmpDir, manifestsFileName),
opts: []Option{WithUntar()},
wantErr: true,
wantErrType: ErrDigestMismatch,
},
{
name: "fails with not found error",
Expand All @@ -163,7 +165,12 @@ func TestArchiveFetcher_FetchWithContext(t *testing.T) {
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
if tt.wantErrType != nil {
g.Expect(err).To(Equal(tt.wantErrType))
g.Expect(err).To(MatchError(tt.wantErrType))
}
if tt.wantErrType == ErrDigestMismatch {
g.Expect(err.Error()).To(ContainSubstring("computed digest doesn't match provided"))
} else {
g.Expect(errors.Is(err, ErrDigestMismatch)).To(BeFalse())
}
} else {
g.Expect(err).ToNot(HaveOccurred())
Expand Down Expand Up @@ -222,10 +229,11 @@ func TestArchiveFetcher_FetchBytes(t *testing.T) {
wantErr: true,
},
{
name: "fails to verify the digest",
url: artifactURL,
digest: "sha256:5c234ee52ff0e3dcc8528d6b9383cc235ad13a11658466f29df3be9eda6ee447",
wantErr: true,
name: "fails to verify the digest",
url: artifactURL,
digest: "sha256:5c234ee52ff0e3dcc8528d6b9383cc235ad13a11658466f29df3be9eda6ee447",
wantErr: true,
wantErrType: ErrDigestMismatch,
},
{
name: "fails with not found error",
Expand All @@ -245,7 +253,12 @@ func TestArchiveFetcher_FetchBytes(t *testing.T) {
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
if tt.wantErrType != nil {
g.Expect(err).To(Equal(tt.wantErrType))
g.Expect(err).To(MatchError(tt.wantErrType))
}
if tt.wantErrType == ErrDigestMismatch {
g.Expect(err.Error()).To(ContainSubstring("computed digest doesn't match provided"))
} else {
g.Expect(errors.Is(err, ErrDigestMismatch)).To(BeFalse())
}
return
}
Expand Down Expand Up @@ -390,6 +403,7 @@ func TestArchiveFetcher_Fetch(t *testing.T) {
maxDownloadSize: -1,
maxUntarSize: -1,
wantErr: true,
wantErrType: ErrDigestMismatch,
},
{
name: "fails with not found error",
Expand All @@ -412,7 +426,12 @@ func TestArchiveFetcher_Fetch(t *testing.T) {
if tt.wantErr {
g.Expect(err).To(HaveOccurred())
if tt.wantErrType != nil {
g.Expect(err).To(Equal(tt.wantErrType))
g.Expect(err).To(MatchError(tt.wantErrType))
}
if tt.wantErrType == ErrDigestMismatch {
g.Expect(err.Error()).To(ContainSubstring("computed digest doesn't match provided"))
} else {
g.Expect(errors.Is(err, ErrDigestMismatch)).To(BeFalse())
}
} else {
g.Expect(err).ToNot(HaveOccurred())
Expand Down
Loading