github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/backend/remote-state/s3/backend_test.go (about)

     1  package s3
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/aws/aws-sdk-go/aws"
    10  	"github.com/aws/aws-sdk-go/service/dynamodb"
    11  	"github.com/aws/aws-sdk-go/service/s3"
    12  	"github.com/hashicorp/terraform/backend"
    13  )
    14  
    15  // verify that we are doing ACC tests or the S3 tests specifically
    16  func testACC(t *testing.T) {
    17  	skip := os.Getenv("TF_ACC") == "" && os.Getenv("TF_S3_TEST") == ""
    18  	if skip {
    19  		t.Log("s3 backend tests require setting TF_ACC or TF_S3_TEST")
    20  		t.Skip()
    21  	}
    22  	if os.Getenv("AWS_DEFAULT_REGION") == "" {
    23  		os.Setenv("AWS_DEFAULT_REGION", "us-west-2")
    24  	}
    25  }
    26  
    27  func TestBackend_impl(t *testing.T) {
    28  	var _ backend.Backend = new(Backend)
    29  }
    30  
    31  func TestBackendConfig(t *testing.T) {
    32  	testACC(t)
    33  	config := map[string]interface{}{
    34  		"region":     "us-west-1",
    35  		"bucket":     "tf-test",
    36  		"key":        "state",
    37  		"encrypt":    true,
    38  		"lock_table": "dynamoTable",
    39  	}
    40  
    41  	b := backend.TestBackendConfig(t, New(), config).(*Backend)
    42  
    43  	if *b.s3Client.Config.Region != "us-west-1" {
    44  		t.Fatalf("Incorrect region was populated")
    45  	}
    46  	if b.bucketName != "tf-test" {
    47  		t.Fatalf("Incorrect bucketName was populated")
    48  	}
    49  	if b.keyName != "state" {
    50  		t.Fatalf("Incorrect keyName was populated")
    51  	}
    52  
    53  	credentials, err := b.s3Client.Config.Credentials.Get()
    54  	if err != nil {
    55  		t.Fatalf("Error when requesting credentials")
    56  	}
    57  	if credentials.AccessKeyID == "" {
    58  		t.Fatalf("No Access Key Id was populated")
    59  	}
    60  	if credentials.SecretAccessKey == "" {
    61  		t.Fatalf("No Secret Access Key was populated")
    62  	}
    63  }
    64  
    65  func TestBackend(t *testing.T) {
    66  	testACC(t)
    67  
    68  	bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix())
    69  	keyName := "testState"
    70  
    71  	b := backend.TestBackendConfig(t, New(), map[string]interface{}{
    72  		"bucket":  bucketName,
    73  		"key":     keyName,
    74  		"encrypt": true,
    75  	}).(*Backend)
    76  
    77  	createS3Bucket(t, b.s3Client, bucketName)
    78  	defer deleteS3Bucket(t, b.s3Client, bucketName)
    79  
    80  	backend.TestBackend(t, b, nil)
    81  }
    82  
    83  func TestBackendLocked(t *testing.T) {
    84  	testACC(t)
    85  
    86  	bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix())
    87  	keyName := "testState"
    88  
    89  	b1 := backend.TestBackendConfig(t, New(), map[string]interface{}{
    90  		"bucket":     bucketName,
    91  		"key":        keyName,
    92  		"encrypt":    true,
    93  		"lock_table": bucketName,
    94  	}).(*Backend)
    95  
    96  	b2 := backend.TestBackendConfig(t, New(), map[string]interface{}{
    97  		"bucket":     bucketName,
    98  		"key":        keyName,
    99  		"encrypt":    true,
   100  		"lock_table": bucketName,
   101  	}).(*Backend)
   102  
   103  	createS3Bucket(t, b1.s3Client, bucketName)
   104  	defer deleteS3Bucket(t, b1.s3Client, bucketName)
   105  	createDynamoDBTable(t, b1.dynClient, bucketName)
   106  	defer deleteDynamoDBTable(t, b1.dynClient, bucketName)
   107  
   108  	backend.TestBackend(t, b1, b2)
   109  }
   110  
   111  func createS3Bucket(t *testing.T, s3Client *s3.S3, bucketName string) {
   112  	createBucketReq := &s3.CreateBucketInput{
   113  		Bucket: &bucketName,
   114  	}
   115  
   116  	// Be clear about what we're doing in case the user needs to clean
   117  	// this up later.
   118  	t.Logf("creating S3 bucket %s in %s", bucketName, *s3Client.Config.Region)
   119  	_, err := s3Client.CreateBucket(createBucketReq)
   120  	if err != nil {
   121  		t.Fatal("failed to create test S3 bucket:", err)
   122  	}
   123  }
   124  
   125  func deleteS3Bucket(t *testing.T, s3Client *s3.S3, bucketName string) {
   126  	warning := "WARNING: Failed to delete the test S3 bucket. It may have been left in your AWS account and may incur storage charges. (error was %s)"
   127  
   128  	// first we have to get rid of the env objects, or we can't delete the bucket
   129  	resp, err := s3Client.ListObjects(&s3.ListObjectsInput{Bucket: &bucketName})
   130  	if err != nil {
   131  		t.Logf(warning, err)
   132  		return
   133  	}
   134  	for _, obj := range resp.Contents {
   135  		if _, err := s3Client.DeleteObject(&s3.DeleteObjectInput{Bucket: &bucketName, Key: obj.Key}); err != nil {
   136  			// this will need cleanup no matter what, so just warn and exit
   137  			t.Logf(warning, err)
   138  			return
   139  		}
   140  	}
   141  
   142  	if _, err := s3Client.DeleteBucket(&s3.DeleteBucketInput{Bucket: &bucketName}); err != nil {
   143  		t.Logf(warning, err)
   144  	}
   145  }
   146  
   147  // create the dynamoDB table, and wait until we can query it.
   148  func createDynamoDBTable(t *testing.T, dynClient *dynamodb.DynamoDB, tableName string) {
   149  	createInput := &dynamodb.CreateTableInput{
   150  		AttributeDefinitions: []*dynamodb.AttributeDefinition{
   151  			{
   152  				AttributeName: aws.String("LockID"),
   153  				AttributeType: aws.String("S"),
   154  			},
   155  		},
   156  		KeySchema: []*dynamodb.KeySchemaElement{
   157  			{
   158  				AttributeName: aws.String("LockID"),
   159  				KeyType:       aws.String("HASH"),
   160  			},
   161  		},
   162  		ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
   163  			ReadCapacityUnits:  aws.Int64(5),
   164  			WriteCapacityUnits: aws.Int64(5),
   165  		},
   166  		TableName: aws.String(tableName),
   167  	}
   168  
   169  	_, err := dynClient.CreateTable(createInput)
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  
   174  	// now wait until it's ACTIVE
   175  	start := time.Now()
   176  	time.Sleep(time.Second)
   177  
   178  	describeInput := &dynamodb.DescribeTableInput{
   179  		TableName: aws.String(tableName),
   180  	}
   181  
   182  	for {
   183  		resp, err := dynClient.DescribeTable(describeInput)
   184  		if err != nil {
   185  			t.Fatal(err)
   186  		}
   187  
   188  		if *resp.Table.TableStatus == "ACTIVE" {
   189  			return
   190  		}
   191  
   192  		if time.Since(start) > time.Minute {
   193  			t.Fatalf("timed out creating DynamoDB table %s", tableName)
   194  		}
   195  
   196  		time.Sleep(3 * time.Second)
   197  	}
   198  
   199  }
   200  
   201  func deleteDynamoDBTable(t *testing.T, dynClient *dynamodb.DynamoDB, tableName string) {
   202  	params := &dynamodb.DeleteTableInput{
   203  		TableName: aws.String(tableName),
   204  	}
   205  	_, err := dynClient.DeleteTable(params)
   206  	if err != nil {
   207  		t.Logf("WARNING: Failed to delete the test DynamoDB table %q. It has been left in your AWS account and may incur charges. (error was %s)", tableName, err)
   208  	}
   209  }