gke-deploy/core/gcs/gcs.go (66 lines of code) (raw):

// Package gcs contains logic related to Google Cloud Storage. package gcs import ( "context" "errors" "strings" "time" "github.com/GoogleCloudPlatform/cloud-builders/gke-deploy/services" ) const ( timeoutErr = "GCS timeout" ) var ( defaultTimeout = 1 * time.Hour defaultDelay = 2 * time.Second errGCSTimeout = errors.New(timeoutErr) ) type GCS struct { Timeout time.Duration Retries int Delay time.Duration GcsService services.GcsService } // Download copies file(s) from GCS. <dst> should be a directory, not a path to a file. func (s *GCS) Download(ctx context.Context, src, dst string, recursive bool) error { return s.copyWithRetry(ctx, src, dst, recursive) } // Upload copies file(s) to GCS. func (s *GCS) Upload(ctx context.Context, src, dst string) error { return s.copyWithRetry(ctx, src, dst, false) } // copyWithRetry is responsible for trying (and retrying) to call copyWithTimeout() // with appropriate retry backoff. func (s *GCS) copyWithRetry(ctx context.Context, src, dst string, recursive bool) error { var err error delay := s.Delay if delay == 0 { delay = defaultDelay } for retryNum := 0; retryNum <= s.Retries; retryNum++ { if retryNum > 0 { time.Sleep(delay) } timeout := s.timeout() e := s.copyWithTimeout(ctx, src, dst, recursive, timeout) if e != nil { err = e if strings.Contains(err.Error(), "AccessDeniedException") { return err } continue } return nil } return err } // copyWithTimeout calls GcsService to move the files. The call will time out if it // takes too long. func (s *GCS) copyWithTimeout(ctx context.Context, src, dst string, recursive bool, timeout time.Duration) error { ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() err := s.GcsService.Copy(ctx, src, dst, recursive) if ctx.Err() == context.DeadlineExceeded { return errGCSTimeout } return err } //timeout returns the GCS timeout that will be used to call GcsService. func (s *GCS) timeout() time.Duration { if s.Timeout == 0 { return defaultTimeout } return s.Timeout }