github.com/mponton/terratest@v0.44.0/modules/gcp/storage.go (about)

     1  package gcp
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  
     8  	"cloud.google.com/go/storage"
     9  	"github.com/mponton/terratest/modules/logger"
    10  	"github.com/mponton/terratest/modules/testing"
    11  	"google.golang.org/api/iterator"
    12  )
    13  
    14  // CreateStorageBucket creates a Google Cloud bucket with the given BucketAttrs. Note that Google Storage bucket names must be globally unique.
    15  func CreateStorageBucket(t testing.TestingT, projectID string, name string, attr *storage.BucketAttrs) {
    16  	err := CreateStorageBucketE(t, projectID, name, attr)
    17  	if err != nil {
    18  		t.Fatal(err)
    19  	}
    20  }
    21  
    22  // CreateStorageBucketE creates a Google Cloud bucket with the given BucketAttrs. Note that Google Storage bucket names must be globally unique.
    23  func CreateStorageBucketE(t testing.TestingT, projectID string, name string, attr *storage.BucketAttrs) error {
    24  	logger.Logf(t, "Creating bucket %s", name)
    25  
    26  	ctx := context.Background()
    27  
    28  	// Creates a client.
    29  	client, err := storage.NewClient(ctx)
    30  	if err != nil {
    31  		return err
    32  	}
    33  
    34  	// Creates a Bucket instance.
    35  	bucket := client.Bucket(name)
    36  
    37  	// Creates the new bucket.
    38  	return bucket.Create(ctx, projectID, attr)
    39  }
    40  
    41  // DeleteStorageBucket destroys the Google Storage bucket.
    42  func DeleteStorageBucket(t testing.TestingT, name string) {
    43  	err := DeleteStorageBucketE(t, name)
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  }
    48  
    49  // DeleteStorageBucketE destroys the S3 bucket in the given region with the given name.
    50  func DeleteStorageBucketE(t testing.TestingT, name string) error {
    51  	logger.Logf(t, "Deleting bucket %s", name)
    52  
    53  	ctx := context.Background()
    54  
    55  	client, err := storage.NewClient(ctx)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	return client.Bucket(name).Delete(ctx)
    61  }
    62  
    63  // ReadBucketObject reads an object from the given Storage Bucket and returns its contents.
    64  func ReadBucketObject(t testing.TestingT, bucketName string, filePath string) io.Reader {
    65  	out, err := ReadBucketObjectE(t, bucketName, filePath)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  	return out
    70  }
    71  
    72  // ReadBucketObjectE reads an object from the given Storage Bucket and returns its contents.
    73  func ReadBucketObjectE(t testing.TestingT, bucketName string, filePath string) (io.Reader, error) {
    74  	logger.Logf(t, "Reading object from bucket %s using path %s", bucketName, filePath)
    75  
    76  	ctx := context.Background()
    77  
    78  	client, err := storage.NewClient(ctx)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	bucket := client.Bucket(bucketName)
    84  	r, err := bucket.Object(filePath).NewReader(ctx)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	return r, nil
    90  }
    91  
    92  // WriteBucketObject writes an object to the given Storage Bucket and returns its URL.
    93  func WriteBucketObject(t testing.TestingT, bucketName string, filePath string, body io.Reader, contentType string) string {
    94  	out, err := WriteBucketObjectE(t, bucketName, filePath, body, contentType)
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	return out
    99  }
   100  
   101  // WriteBucketObjectE writes an object to the given Storage Bucket and returns its URL.
   102  func WriteBucketObjectE(t testing.TestingT, bucketName string, filePath string, body io.Reader, contentType string) (string, error) {
   103  	// set a default content type
   104  	if contentType == "" {
   105  		contentType = "application/octet-stream"
   106  	}
   107  
   108  	logger.Logf(t, "Writing object to bucket %s using path %s and content type %s", bucketName, filePath, contentType)
   109  
   110  	ctx := context.Background()
   111  
   112  	client, err := storage.NewClient(ctx)
   113  	if err != nil {
   114  		return "", err
   115  	}
   116  
   117  	w := client.Bucket(bucketName).Object(filePath).NewWriter(ctx)
   118  	w.ContentType = contentType
   119  
   120  	// Don't set any ACL or cache control properties for now
   121  	//w.ACL = []storage.ACLRule{{Entity: storage.AllAuthenticatedUsers, Role: storage.RoleReader}}
   122  	// set a default cache control (1 day)
   123  	//w.CacheControl = "public, max-age=86400"
   124  
   125  	if _, err := io.Copy(w, body); err != nil {
   126  		return "", err
   127  	}
   128  	if err := w.Close(); err != nil {
   129  		return "", err
   130  	}
   131  
   132  	const publicURL = "https://storage.googleapis.com/%s/%s"
   133  	return fmt.Sprintf(publicURL, bucketName, filePath), nil
   134  }
   135  
   136  // EmptyStorageBucket removes the contents of a storage bucket with the given name.
   137  func EmptyStorageBucket(t testing.TestingT, name string) {
   138  	err := EmptyStorageBucketE(t, name)
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  }
   143  
   144  // EmptyStorageBucketE removes the contents of a storage bucket with the given name.
   145  func EmptyStorageBucketE(t testing.TestingT, name string) error {
   146  	logger.Logf(t, "Emptying storage bucket %s", name)
   147  
   148  	ctx := context.Background()
   149  
   150  	client, err := storage.NewClient(ctx)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	// List all objects in the bucket
   156  	//
   157  	// TODO - we should really do a bulk delete call here, but I couldn't find
   158  	// anything in the SDK.
   159  	bucket := client.Bucket(name)
   160  	it := bucket.Objects(ctx, nil)
   161  	for {
   162  		objectAttrs, err := it.Next()
   163  
   164  		if err == iterator.Done {
   165  			break
   166  		}
   167  
   168  		if err != nil {
   169  			return err
   170  		}
   171  
   172  		// purge the object
   173  		logger.Logf(t, "Deleting storage bucket object %s", objectAttrs.Name)
   174  		bucket.Object(objectAttrs.Name).Delete(ctx)
   175  	}
   176  
   177  	return nil
   178  }
   179  
   180  // AssertStorageBucketExists checks if the given storage bucket exists and fails the test if it does not.
   181  func AssertStorageBucketExists(t testing.TestingT, name string) {
   182  	err := AssertStorageBucketExistsE(t, name)
   183  	if err != nil {
   184  		t.Fatal(err)
   185  	}
   186  }
   187  
   188  // AssertStorageBucketExistsE checks if the given storage bucket exists and returns an error if it does not.
   189  func AssertStorageBucketExistsE(t testing.TestingT, name string) error {
   190  	logger.Logf(t, "Finding bucket %s", name)
   191  
   192  	ctx := context.Background()
   193  
   194  	// Creates a client.
   195  	client, err := storage.NewClient(ctx)
   196  	if err != nil {
   197  		return err
   198  	}
   199  
   200  	// Creates a Bucket instance.
   201  	bucket := client.Bucket(name)
   202  
   203  	// TODO - the code below attempts to determine whether the storage bucket
   204  	// exists by making a making a number of API calls, then attemping to
   205  	// list the contents of the bucket. It was adapted from Google's own integration
   206  	// tests and should be improved once the appropriate API call is added.
   207  	// For more info see: https://github.com/GoogleCloudPlatform/google-cloud-go/blob/de879f7be552d57556875b8aaa383bce9396cc8c/storage/integration_test.go#L1231
   208  	if _, err := bucket.Attrs(ctx); err != nil {
   209  		// ErrBucketNotExist
   210  		return err
   211  	}
   212  
   213  	it := bucket.Objects(ctx, nil)
   214  	if _, err := it.Next(); err == storage.ErrBucketNotExist {
   215  		return err
   216  	}
   217  
   218  	return nil
   219  }