in gcs-fetcher/pkg/fetcher/fetcher.go [352:425]
func (gf *Fetcher) fetchObjectOnce(ctx context.Context, j job, dest string, breakerSig <-chan struct{}) fetchOnceResult {
var result fetchOnceResult
r, err := gf.GCS.NewReader(ctx, j.bucket, j.object)
if err != nil {
// Check for AccessDenied failure here and return a useful error message on Stderr and exit immediately.
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == http.StatusForbidden {
// Try to parse out the robot name.
match := robotRegex.FindStringSubmatch(err.Error())
robot := "your Cloud Build service account"
if len(match) == 2 {
robot = match[1]
}
result.err = &permissionError{bucket: j.bucket, robot: robot}
return result
}
result.err = fmt.Errorf("creating GCS reader for %q: %v", formatGCSName(j.bucket, j.object, j.generation), err)
return result
}
defer func() {
if cerr := r.Close(); cerr != nil {
result.err = fmt.Errorf("Failed to close GCS reader: %v", cerr)
}
}()
// If we're cancelled, just return.
select {
case <-breakerSig:
result.err = errGCSTimeout
return result
default:
// Fallthrough
}
f, err := gf.OS.Create(dest)
if err != nil {
result.err = fmt.Errorf("creating destination file %q: %v", dest, err)
return result
}
defer func() {
if cerr := f.Close(); cerr != nil {
result.err = fmt.Errorf("Failed to close file %q: %v", dest, cerr)
}
}()
h := sha1.New()
n, err := io.Copy(f, io.TeeReader(r, h))
if err != nil {
result.err = fmt.Errorf("copying bytes from %q to %q: %v", formatGCSName(j.bucket, j.object, j.generation), dest, err)
return result
}
// If we're cancelled, just return.
select {
case <-breakerSig:
result.err = errGCSTimeout
return result
default:
// Fallthrough
}
result.size = sizeBytes(n)
// Verify the sha1sum before declaring success.
if j.sha1sum != "" {
got := strings.ToLower(fmt.Sprintf("%x", h.Sum(nil)))
want := strings.ToLower(nonHexRegex.ReplaceAllString(j.sha1sum, ""))
if got != want {
result.err = fmt.Errorf("%s SHA mismatch, got %q, want %q", j.filename, got, want)
return result
}
}
return result
}