github.com/chentex/terraform@v0.11.2-0.20171208003256-252e8145842e/backend/remote-state/gcs/backend_test.go (about)

     1  package gcs
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	"cloud.google.com/go/storage"
    12  	"github.com/hashicorp/terraform/backend"
    13  	"github.com/hashicorp/terraform/state/remote"
    14  )
    15  
    16  const noPrefix = ""
    17  
    18  func TestStateFile(t *testing.T) {
    19  	t.Parallel()
    20  
    21  	cases := []struct {
    22  		prefix           string
    23  		defaultStateFile string
    24  		name             string
    25  		wantStateFile    string
    26  		wantLockFile     string
    27  	}{
    28  		{"state", "", "default", "state/default.tfstate", "state/default.tflock"},
    29  		{"state", "", "test", "state/test.tfstate", "state/test.tflock"},
    30  		{"state", "legacy.tfstate", "default", "legacy.tfstate", "legacy.tflock"},
    31  		{"state", "legacy.tfstate", "test", "state/test.tfstate", "state/test.tflock"},
    32  		{"state", "legacy.state", "default", "legacy.state", "legacy.state.tflock"},
    33  		{"state", "legacy.state", "test", "state/test.tfstate", "state/test.tflock"},
    34  	}
    35  	for _, c := range cases {
    36  		b := &gcsBackend{
    37  			prefix:           c.prefix,
    38  			defaultStateFile: c.defaultStateFile,
    39  		}
    40  
    41  		if got := b.stateFile(c.name); got != c.wantStateFile {
    42  			t.Errorf("stateFile(%q) = %q, want %q", c.name, got, c.wantStateFile)
    43  		}
    44  
    45  		if got := b.lockFile(c.name); got != c.wantLockFile {
    46  			t.Errorf("lockFile(%q) = %q, want %q", c.name, got, c.wantLockFile)
    47  		}
    48  	}
    49  }
    50  
    51  func TestRemoteClient(t *testing.T) {
    52  	t.Parallel()
    53  
    54  	bucket := bucketName(t)
    55  	be := setupBackend(t, bucket, noPrefix)
    56  	defer teardownBackend(t, be, noPrefix)
    57  
    58  	ss, err := be.State(backend.DefaultStateName)
    59  	if err != nil {
    60  		t.Fatalf("be.State(%q) = %v", backend.DefaultStateName, err)
    61  	}
    62  
    63  	rs, ok := ss.(*remote.State)
    64  	if !ok {
    65  		t.Fatalf("be.State(): got a %T, want a *remote.State", ss)
    66  	}
    67  
    68  	remote.TestClient(t, rs.Client)
    69  }
    70  
    71  func TestRemoteLocks(t *testing.T) {
    72  	t.Parallel()
    73  
    74  	bucket := bucketName(t)
    75  	be := setupBackend(t, bucket, noPrefix)
    76  	defer teardownBackend(t, be, noPrefix)
    77  
    78  	remoteClient := func() (remote.Client, error) {
    79  		ss, err := be.State(backend.DefaultStateName)
    80  		if err != nil {
    81  			return nil, err
    82  		}
    83  
    84  		rs, ok := ss.(*remote.State)
    85  		if !ok {
    86  			return nil, fmt.Errorf("be.State(): got a %T, want a *remote.State", ss)
    87  		}
    88  
    89  		return rs.Client, nil
    90  	}
    91  
    92  	c0, err := remoteClient()
    93  	if err != nil {
    94  		t.Fatalf("remoteClient(0) = %v", err)
    95  	}
    96  	c1, err := remoteClient()
    97  	if err != nil {
    98  		t.Fatalf("remoteClient(1) = %v", err)
    99  	}
   100  
   101  	remote.TestRemoteLocks(t, c0, c1)
   102  }
   103  
   104  func TestBackend(t *testing.T) {
   105  	t.Parallel()
   106  
   107  	bucket := bucketName(t)
   108  
   109  	be0 := setupBackend(t, bucket, noPrefix)
   110  	defer teardownBackend(t, be0, noPrefix)
   111  
   112  	be1 := setupBackend(t, bucket, noPrefix)
   113  
   114  	backend.TestBackend(t, be0, be1)
   115  }
   116  func TestBackendWithPrefix(t *testing.T) {
   117  	t.Parallel()
   118  
   119  	prefix := "test/prefix"
   120  	bucket := bucketName(t)
   121  
   122  	be0 := setupBackend(t, bucket, prefix)
   123  	defer teardownBackend(t, be0, prefix)
   124  
   125  	be1 := setupBackend(t, bucket, prefix+"/")
   126  
   127  	backend.TestBackend(t, be0, be1)
   128  }
   129  
   130  // setupBackend returns a new GCS backend.
   131  func setupBackend(t *testing.T, bucket, prefix string) backend.Backend {
   132  	t.Helper()
   133  
   134  	projectID := os.Getenv("GOOGLE_PROJECT")
   135  	if projectID == "" || os.Getenv("TF_ACC") == "" {
   136  		t.Skip("This test creates a bucket in GCS and populates it. " +
   137  			"Since this may incur costs, it will only run if " +
   138  			"the TF_ACC and GOOGLE_PROJECT environment variables are set.")
   139  	}
   140  
   141  	config := map[string]interface{}{
   142  		"project": projectID,
   143  		"bucket":  bucket,
   144  		"prefix":  prefix,
   145  	}
   146  
   147  	b := backend.TestBackendConfig(t, New(), config)
   148  	be := b.(*gcsBackend)
   149  
   150  	// create the bucket if it doesn't exist
   151  	bkt := be.storageClient.Bucket(bucket)
   152  	_, err := bkt.Attrs(be.storageContext)
   153  	if err != nil {
   154  		if err != storage.ErrBucketNotExist {
   155  			t.Fatal(err)
   156  		}
   157  
   158  		attrs := &storage.BucketAttrs{
   159  			Location: be.region,
   160  		}
   161  		err := bkt.Create(be.storageContext, be.projectID, attrs)
   162  		if err != nil {
   163  			t.Fatal(err)
   164  		}
   165  	}
   166  
   167  	return b
   168  }
   169  
   170  // teardownBackend deletes all states from be except the default state.
   171  func teardownBackend(t *testing.T, be backend.Backend, prefix string) {
   172  	t.Helper()
   173  	gcsBE, ok := be.(*gcsBackend)
   174  	if !ok {
   175  		t.Fatalf("be is a %T, want a *gcsBackend", be)
   176  	}
   177  	ctx := gcsBE.storageContext
   178  
   179  	bucket := gcsBE.storageClient.Bucket(gcsBE.bucketName)
   180  	objs := bucket.Objects(ctx, nil)
   181  
   182  	for o, err := objs.Next(); err == nil; o, err = objs.Next() {
   183  		if err := bucket.Object(o.Name).Delete(ctx); err != nil {
   184  			log.Printf("Error trying to delete object: %s %s\n\n", o.Name, err)
   185  		} else {
   186  			log.Printf("Object deleted: %s", o.Name)
   187  		}
   188  	}
   189  
   190  	// Delete the bucket itself.
   191  	if err := bucket.Delete(ctx); err != nil {
   192  		t.Errorf("deleting bucket %q failed, manual cleanup may be required: %v", gcsBE.bucketName, err)
   193  	}
   194  }
   195  
   196  // bucketName returns a valid bucket name for this test.
   197  func bucketName(t *testing.T) string {
   198  	name := fmt.Sprintf("tf-%x-%s", time.Now().UnixNano(), t.Name())
   199  
   200  	// Bucket names must contain 3 to 63 characters.
   201  	if len(name) > 63 {
   202  		name = name[:63]
   203  	}
   204  
   205  	return strings.ToLower(name)
   206  }