...

Source file src/github.com/docker/distribution/registry/storage/driver/gcs/gcs_test.go

Documentation: github.com/docker/distribution/registry/storage/driver/gcs

     1  //go:build include_gcs
     2  // +build include_gcs
     3  
     4  package gcs
     5  
     6  import (
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"testing"
    11  
    12  	dcontext "github.com/docker/distribution/context"
    13  	storagedriver "github.com/docker/distribution/registry/storage/driver"
    14  	"github.com/docker/distribution/registry/storage/driver/testsuites"
    15  	"golang.org/x/oauth2"
    16  	"golang.org/x/oauth2/google"
    17  	"google.golang.org/api/googleapi"
    18  	"google.golang.org/cloud/storage"
    19  	"gopkg.in/check.v1"
    20  )
    21  
    22  // Hook up gocheck into the "go test" runner.
    23  func Test(t *testing.T) { check.TestingT(t) }
    24  
    25  var gcsDriverConstructor func(rootDirectory string) (storagedriver.StorageDriver, error)
    26  var skipGCS func() string
    27  
    28  func init() {
    29  	bucket := os.Getenv("REGISTRY_STORAGE_GCS_BUCKET")
    30  	credentials := os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")
    31  
    32  	// Skip GCS storage driver tests if environment variable parameters are not provided
    33  	skipGCS = func() string {
    34  		if bucket == "" || credentials == "" {
    35  			return "The following environment variables must be set to enable these tests: REGISTRY_STORAGE_GCS_BUCKET, GOOGLE_APPLICATION_CREDENTIALS"
    36  		}
    37  		return ""
    38  	}
    39  
    40  	if skipGCS() != "" {
    41  		return
    42  	}
    43  
    44  	root, err := ioutil.TempDir("", "driver-")
    45  	if err != nil {
    46  		panic(err)
    47  	}
    48  	defer os.Remove(root)
    49  	var ts oauth2.TokenSource
    50  	var email string
    51  	var privateKey []byte
    52  
    53  	ts, err = google.DefaultTokenSource(dcontext.Background(), storage.ScopeFullControl)
    54  	if err != nil {
    55  		// Assume that the file contents are within the environment variable since it exists
    56  		// but does not contain a valid file path
    57  		jwtConfig, err := google.JWTConfigFromJSON([]byte(credentials), storage.ScopeFullControl)
    58  		if err != nil {
    59  			panic(fmt.Sprintf("Error reading JWT config : %s", err))
    60  		}
    61  		email = jwtConfig.Email
    62  		privateKey = jwtConfig.PrivateKey
    63  		if len(privateKey) == 0 {
    64  			panic("Error reading JWT config : missing private_key property")
    65  		}
    66  		if email == "" {
    67  			panic("Error reading JWT config : missing client_email property")
    68  		}
    69  		ts = jwtConfig.TokenSource(dcontext.Background())
    70  	}
    71  
    72  	gcsDriverConstructor = func(rootDirectory string) (storagedriver.StorageDriver, error) {
    73  		parameters := driverParameters{
    74  			bucket:        bucket,
    75  			rootDirectory: root,
    76  			email:         email,
    77  			privateKey:    privateKey,
    78  			client:        oauth2.NewClient(dcontext.Background(), ts),
    79  			chunkSize:     defaultChunkSize,
    80  		}
    81  
    82  		return New(parameters)
    83  	}
    84  
    85  	testsuites.RegisterSuite(func() (storagedriver.StorageDriver, error) {
    86  		return gcsDriverConstructor(root)
    87  	}, skipGCS)
    88  }
    89  
    90  // Test Committing a FileWriter without having called Write
    91  func TestCommitEmpty(t *testing.T) {
    92  	if skipGCS() != "" {
    93  		t.Skip(skipGCS())
    94  	}
    95  
    96  	validRoot, err := ioutil.TempDir("", "driver-")
    97  	if err != nil {
    98  		t.Fatalf("unexpected error creating temporary directory: %v", err)
    99  	}
   100  	defer os.Remove(validRoot)
   101  
   102  	driver, err := gcsDriverConstructor(validRoot)
   103  	if err != nil {
   104  		t.Fatalf("unexpected error creating rooted driver: %v", err)
   105  	}
   106  
   107  	filename := "/test"
   108  	ctx := dcontext.Background()
   109  
   110  	writer, err := driver.Writer(ctx, filename, false)
   111  	defer driver.Delete(ctx, filename)
   112  	if err != nil {
   113  		t.Fatalf("driver.Writer: unexpected error: %v", err)
   114  	}
   115  	err = writer.Commit()
   116  	if err != nil {
   117  		t.Fatalf("writer.Commit: unexpected error: %v", err)
   118  	}
   119  	err = writer.Close()
   120  	if err != nil {
   121  		t.Fatalf("writer.Close: unexpected error: %v", err)
   122  	}
   123  	if writer.Size() != 0 {
   124  		t.Fatalf("writer.Size: %d != 0", writer.Size())
   125  	}
   126  	readContents, err := driver.GetContent(ctx, filename)
   127  	if err != nil {
   128  		t.Fatalf("driver.GetContent: unexpected error: %v", err)
   129  	}
   130  	if len(readContents) != 0 {
   131  		t.Fatalf("len(driver.GetContent(..)): %d != 0", len(readContents))
   132  	}
   133  }
   134  
   135  // Test Committing a FileWriter after having written exactly
   136  // defaultChunksize bytes.
   137  func TestCommit(t *testing.T) {
   138  	if skipGCS() != "" {
   139  		t.Skip(skipGCS())
   140  	}
   141  
   142  	validRoot, err := ioutil.TempDir("", "driver-")
   143  	if err != nil {
   144  		t.Fatalf("unexpected error creating temporary directory: %v", err)
   145  	}
   146  	defer os.Remove(validRoot)
   147  
   148  	driver, err := gcsDriverConstructor(validRoot)
   149  	if err != nil {
   150  		t.Fatalf("unexpected error creating rooted driver: %v", err)
   151  	}
   152  
   153  	filename := "/test"
   154  	ctx := dcontext.Background()
   155  
   156  	contents := make([]byte, defaultChunkSize)
   157  	writer, err := driver.Writer(ctx, filename, false)
   158  	defer driver.Delete(ctx, filename)
   159  	if err != nil {
   160  		t.Fatalf("driver.Writer: unexpected error: %v", err)
   161  	}
   162  	_, err = writer.Write(contents)
   163  	if err != nil {
   164  		t.Fatalf("writer.Write: unexpected error: %v", err)
   165  	}
   166  	err = writer.Commit()
   167  	if err != nil {
   168  		t.Fatalf("writer.Commit: unexpected error: %v", err)
   169  	}
   170  	err = writer.Close()
   171  	if err != nil {
   172  		t.Fatalf("writer.Close: unexpected error: %v", err)
   173  	}
   174  	if writer.Size() != int64(len(contents)) {
   175  		t.Fatalf("writer.Size: %d != %d", writer.Size(), len(contents))
   176  	}
   177  	readContents, err := driver.GetContent(ctx, filename)
   178  	if err != nil {
   179  		t.Fatalf("driver.GetContent: unexpected error: %v", err)
   180  	}
   181  	if len(readContents) != len(contents) {
   182  		t.Fatalf("len(driver.GetContent(..)): %d != %d", len(readContents), len(contents))
   183  	}
   184  }
   185  
   186  func TestRetry(t *testing.T) {
   187  	if skipGCS() != "" {
   188  		t.Skip(skipGCS())
   189  	}
   190  
   191  	assertError := func(expected string, observed error) {
   192  		observedMsg := "<nil>"
   193  		if observed != nil {
   194  			observedMsg = observed.Error()
   195  		}
   196  		if observedMsg != expected {
   197  			t.Fatalf("expected %v, observed %v\n", expected, observedMsg)
   198  		}
   199  	}
   200  
   201  	err := retry(func() error {
   202  		return &googleapi.Error{
   203  			Code:    503,
   204  			Message: "google api error",
   205  		}
   206  	})
   207  	assertError("googleapi: Error 503: google api error", err)
   208  
   209  	err = retry(func() error {
   210  		return &googleapi.Error{
   211  			Code:    404,
   212  			Message: "google api error",
   213  		}
   214  	})
   215  	assertError("googleapi: Error 404: google api error", err)
   216  
   217  	err = retry(func() error {
   218  		return fmt.Errorf("error")
   219  	})
   220  	assertError("error", err)
   221  }
   222  
   223  func TestEmptyRootList(t *testing.T) {
   224  	if skipGCS() != "" {
   225  		t.Skip(skipGCS())
   226  	}
   227  
   228  	validRoot, err := ioutil.TempDir("", "driver-")
   229  	if err != nil {
   230  		t.Fatalf("unexpected error creating temporary directory: %v", err)
   231  	}
   232  	defer os.Remove(validRoot)
   233  
   234  	rootedDriver, err := gcsDriverConstructor(validRoot)
   235  	if err != nil {
   236  		t.Fatalf("unexpected error creating rooted driver: %v", err)
   237  	}
   238  
   239  	emptyRootDriver, err := gcsDriverConstructor("")
   240  	if err != nil {
   241  		t.Fatalf("unexpected error creating empty root driver: %v", err)
   242  	}
   243  
   244  	slashRootDriver, err := gcsDriverConstructor("/")
   245  	if err != nil {
   246  		t.Fatalf("unexpected error creating slash root driver: %v", err)
   247  	}
   248  
   249  	filename := "/test"
   250  	contents := []byte("contents")
   251  	ctx := dcontext.Background()
   252  	err = rootedDriver.PutContent(ctx, filename, contents)
   253  	if err != nil {
   254  		t.Fatalf("unexpected error creating content: %v", err)
   255  	}
   256  	defer func() {
   257  		err := rootedDriver.Delete(ctx, filename)
   258  		if err != nil {
   259  			t.Fatalf("failed to remove %v due to %v\n", filename, err)
   260  		}
   261  	}()
   262  	keys, err := emptyRootDriver.List(ctx, "/")
   263  	if err != nil {
   264  		t.Fatalf("unexpected error listing empty root content: %v", err)
   265  	}
   266  	for _, path := range keys {
   267  		if !storagedriver.PathRegexp.MatchString(path) {
   268  			t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
   269  		}
   270  	}
   271  
   272  	keys, err = slashRootDriver.List(ctx, "/")
   273  	if err != nil {
   274  		t.Fatalf("unexpected error listing slash root content: %v", err)
   275  	}
   276  	for _, path := range keys {
   277  		if !storagedriver.PathRegexp.MatchString(path) {
   278  			t.Fatalf("unexpected string in path: %q != %q", path, storagedriver.PathRegexp)
   279  		}
   280  	}
   281  }
   282  
   283  // TestMoveDirectory checks that moving a directory returns an error.
   284  func TestMoveDirectory(t *testing.T) {
   285  	if skipGCS() != "" {
   286  		t.Skip(skipGCS())
   287  	}
   288  
   289  	validRoot, err := ioutil.TempDir("", "driver-")
   290  	if err != nil {
   291  		t.Fatalf("unexpected error creating temporary directory: %v", err)
   292  	}
   293  	defer os.Remove(validRoot)
   294  
   295  	driver, err := gcsDriverConstructor(validRoot)
   296  	if err != nil {
   297  		t.Fatalf("unexpected error creating rooted driver: %v", err)
   298  	}
   299  
   300  	ctx := dcontext.Background()
   301  	contents := []byte("contents")
   302  	// Create a regular file.
   303  	err = driver.PutContent(ctx, "/parent/dir/foo", contents)
   304  	if err != nil {
   305  		t.Fatalf("unexpected error creating content: %v", err)
   306  	}
   307  	defer func() {
   308  		err := driver.Delete(ctx, "/parent")
   309  		if err != nil {
   310  			t.Fatalf("failed to remove /parent due to %v\n", err)
   311  		}
   312  	}()
   313  
   314  	err = driver.Move(ctx, "/parent/dir", "/parent/other")
   315  	if err == nil {
   316  		t.Fatalf("Moving directory /parent/dir /parent/other should have return a non-nil error\n")
   317  	}
   318  }
   319  

View as plain text