github.com/secure-build/gitlab-runner@v12.5.0+incompatible/cache/gcs/adapter.go (about)

     1  package gcs
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/url"
     7  	"time"
     8  
     9  	"cloud.google.com/go/storage"
    10  	"github.com/sirupsen/logrus"
    11  
    12  	"gitlab.com/gitlab-org/gitlab-runner/cache"
    13  	"gitlab.com/gitlab-org/gitlab-runner/common"
    14  )
    15  
    16  type signedURLGenerator func(bucket string, name string, opts *storage.SignedURLOptions) (string, error)
    17  
    18  type gcsAdapter struct {
    19  	timeout    time.Duration
    20  	config     *common.CacheGCSConfig
    21  	objectName string
    22  
    23  	generateSignedURL   signedURLGenerator
    24  	credentialsResolver credentialsResolver
    25  }
    26  
    27  func (a *gcsAdapter) GetDownloadURL() *url.URL {
    28  	return a.presignURL(http.MethodGet, "")
    29  }
    30  
    31  func (a *gcsAdapter) GetUploadURL() *url.URL {
    32  	return a.presignURL(http.MethodPut, "application/octet-stream")
    33  }
    34  
    35  func (a *gcsAdapter) presignURL(method string, contentType string) *url.URL {
    36  	err := a.credentialsResolver.Resolve()
    37  	if err != nil {
    38  		logrus.Errorf("error while resolving GCS credentials: %v", err)
    39  		return nil
    40  	}
    41  
    42  	credentials := a.credentialsResolver.Credentials()
    43  
    44  	var privateKey []byte
    45  	if credentials.PrivateKey != "" {
    46  		privateKey = []byte(credentials.PrivateKey)
    47  	}
    48  
    49  	if a.config.BucketName == "" {
    50  		logrus.Error("BucketName can't be empty")
    51  		return nil
    52  	}
    53  
    54  	rawURL, err := a.generateSignedURL(a.config.BucketName, a.objectName, &storage.SignedURLOptions{
    55  		GoogleAccessID: credentials.AccessID,
    56  		PrivateKey:     privateKey,
    57  		Method:         method,
    58  		Expires:        time.Now().Add(a.timeout),
    59  		ContentType:    contentType,
    60  	})
    61  	if err != nil {
    62  		logrus.Errorf("error while generating GCS pre-signed URL: %v", err)
    63  		return nil
    64  	}
    65  
    66  	URL, err := url.Parse(rawURL)
    67  	if err != nil {
    68  		logrus.Errorf("error while parsing generated URL: %v", err)
    69  		return nil
    70  	}
    71  
    72  	return URL
    73  }
    74  
    75  func New(config *common.CacheConfig, timeout time.Duration, objectName string) (cache.Adapter, error) {
    76  	gcs := config.GCS
    77  	if gcs == nil {
    78  		return nil, fmt.Errorf("missing GCS configuration")
    79  	}
    80  
    81  	cr, err := credentialsResolverInitializer(gcs)
    82  	if err != nil {
    83  		return nil, fmt.Errorf("error while initializing GCS credentials resolver: %v", err)
    84  	}
    85  
    86  	a := &gcsAdapter{
    87  		config:              gcs,
    88  		timeout:             timeout,
    89  		objectName:          objectName,
    90  		generateSignedURL:   storage.SignedURL,
    91  		credentialsResolver: cr,
    92  	}
    93  
    94  	return a, nil
    95  }
    96  
    97  func init() {
    98  	err := cache.Factories().Register("gcs", New)
    99  	if err != nil {
   100  		panic(err)
   101  	}
   102  }