github.com/npaton/distribution@v2.3.1-rc.0+incompatible/registry/storage/driver/gcs/gcs_test.go (about)

     1  // +build include_gcs
     2  
     3  package gcs
     4  
     5  import (
     6  	"io/ioutil"
     7  	"os"
     8  	"testing"
     9  
    10  	"fmt"
    11  	ctx "github.com/docker/distribution/context"
    12  	storagedriver "github.com/docker/distribution/registry/storage/driver"
    13  	"github.com/docker/distribution/registry/storage/driver/testsuites"
    14  	"golang.org/x/oauth2"
    15  	"golang.org/x/oauth2/google"
    16  	"google.golang.org/api/googleapi"
    17  	"google.golang.org/cloud/storage"
    18  	"gopkg.in/check.v1"
    19  )
    20  
    21  // Hook up gocheck into the "go test" runner.
    22  func Test(t *testing.T) { check.TestingT(t) }
    23  
    24  var gcsDriverConstructor func(rootDirectory string) (storagedriver.StorageDriver, error)
    25  var skipGCS func() string
    26  
    27  func init() {
    28  	bucket := os.Getenv("REGISTRY_STORAGE_GCS_BUCKET")
    29  	credentials := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
    30  
    31  	// Skip GCS storage driver tests if environment variable parameters are not provided
    32  	skipGCS = func() string {
    33  		if bucket == "" || credentials == "" {
    34  			return "The following environment variables must be set to enable these tests: REGISTRY_STORAGE_GCS_BUCKET, GOOGLE_APPLICATION_CREDENTIALS"
    35  		}
    36  		return ""
    37  	}
    38  
    39  	if skipGCS() != "" {
    40  		return
    41  	}
    42  
    43  	root, err := ioutil.TempDir("", "driver-")
    44  	if err != nil {
    45  		panic(err)
    46  	}
    47  	defer os.Remove(root)
    48  	var ts oauth2.TokenSource
    49  	var email string
    50  	var privateKey []byte
    51  
    52  	ts, err = google.DefaultTokenSource(ctx.Background(), storage.ScopeFullControl)
    53  	if err != nil {
    54  		// Assume that the file contents are within the environment variable since it exists
    55  		// but does not contain a valid file path
    56  		jwtConfig, err := google.JWTConfigFromJSON([]byte(credentials), storage.ScopeFullControl)
    57  		if err != nil {
    58  			panic(fmt.Sprintf("Error reading JWT config : %s", err))
    59  		}
    60  		email = jwtConfig.Email
    61  		privateKey = []byte(jwtConfig.PrivateKey)
    62  		if len(privateKey) == 0 {
    63  			panic("Error reading JWT config : missing private_key property")
    64  		}
    65  		if email == "" {
    66  			panic("Error reading JWT config : missing client_email property")
    67  		}
    68  		ts = jwtConfig.TokenSource(ctx.Background())
    69  	}
    70  
    71  	gcsDriverConstructor = func(rootDirectory string) (storagedriver.StorageDriver, error) {
    72  		parameters := driverParameters{
    73  			bucket:        bucket,
    74  			rootDirectory: root,
    75  			email:         email,
    76  			privateKey:    privateKey,
    77  			client:        oauth2.NewClient(ctx.Background(), ts),
    78  		}
    79  
    80  		return New(parameters)
    81  	}
    82  
    83  	testsuites.RegisterSuite(func() (storagedriver.StorageDriver, error) {
    84  		return gcsDriverConstructor(root)
    85  	}, skipGCS)
    86  }
    87  
    88  func TestRetry(t *testing.T) {
    89  	if skipGCS() != "" {
    90  		t.Skip(skipGCS())
    91  	}
    92  
    93  	assertError := func(expected string, observed error) {
    94  		observedMsg := "<nil>"
    95  		if observed != nil {
    96  			observedMsg = observed.Error()
    97  		}
    98  		if observedMsg != expected {
    99  			t.Fatalf("expected %v, observed %v\n", expected, observedMsg)
   100  		}
   101  	}
   102  
   103  	err := retry(2, func() error {
   104  		return &googleapi.Error{
   105  			Code:    503,
   106  			Message: "google api error",
   107  		}
   108  	})
   109  	assertError("googleapi: Error 503: google api error", err)
   110  
   111  	err = retry(2, func() error {
   112  		return &googleapi.Error{
   113  			Code:    404,
   114  			Message: "google api error",
   115  		}
   116  	})
   117  	assertError("googleapi: Error 404: google api error", err)
   118  
   119  	err = retry(2, func() error {
   120  		return fmt.Errorf("error")
   121  	})
   122  	assertError("error", err)
   123  }
   124  
   125  func TestEmptyRootList(t *testing.T) {
   126  	if skipGCS() != "" {
   127  		t.Skip(skipGCS())
   128  	}
   129  
   130  	validRoot, err := ioutil.TempDir("", "driver-")
   131  	if err != nil {
   132  		t.Fatalf("unexpected error creating temporary directory: %v", err)
   133  	}
   134  	defer os.Remove(validRoot)
   135  
   136  	rootedDriver, err := gcsDriverConstructor(validRoot)
   137  	if err != nil {
   138  		t.Fatalf("unexpected error creating rooted driver: %v", err)
   139  	}
   140  
   141  	emptyRootDriver, err := gcsDriverConstructor("")
   142  	if err != nil {
   143  		t.Fatalf("unexpected error creating empty root driver: %v", err)
   144  	}
   145  
   146  	slashRootDriver, err := gcsDriverConstructor("/")
   147  	if err != nil {
   148  		t.Fatalf("unexpected error creating slash root driver: %v", err)
   149  	}
   150  
   151  	filename := "/test"
   152  	contents := []byte("contents")
   153  	ctx := ctx.Background()
   154  	err = rootedDriver.PutContent(ctx, filename, contents)
   155  	if err != nil {
   156  		t.Fatalf("unexpected error creating content: %v", err)
   157  	}
   158  	defer func() {
   159  		err := rootedDriver.Delete(ctx, filename)
   160  		if err != nil {
   161  			t.Fatalf("failed to remove %v due to %v\n", filename, err)
   162  		}
   163  	}()
   164  	keys, err := emptyRootDriver.List(ctx, "/")
   165  	for _, path := range keys {
   166  		if !storagedriver.PathRegexp.MatchString(path) {
   167  			t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
   168  		}
   169  	}
   170  
   171  	keys, err = slashRootDriver.List(ctx, "/")
   172  	for _, path := range keys {
   173  		if !storagedriver.PathRegexp.MatchString(path) {
   174  			t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
   175  		}
   176  	}
   177  }