github.com/dougneal/terraform@v0.6.15-0.20170330092735-b6a3840768a4/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 // This test just instantiates the client. Shouldn't make any actual 33 // requests nor incur any costs. 34 35 config := map[string]interface{}{ 36 "region": "us-west-1", 37 "bucket": "tf-test", 38 "key": "state", 39 "encrypt": true, 40 "access_key": "ACCESS_KEY", 41 "secret_key": "SECRET_KEY", 42 "lock_table": "dynamoTable", 43 } 44 45 b := backend.TestBackendConfig(t, New(), config).(*Backend) 46 47 if *b.s3Client.Config.Region != "us-west-1" { 48 t.Fatalf("Incorrect region was populated") 49 } 50 if b.bucketName != "tf-test" { 51 t.Fatalf("Incorrect bucketName was populated") 52 } 53 if b.keyName != "state" { 54 t.Fatalf("Incorrect keyName was populated") 55 } 56 57 credentials, err := b.s3Client.Config.Credentials.Get() 58 if err != nil { 59 t.Fatalf("Error when requesting credentials") 60 } 61 if credentials.AccessKeyID != "ACCESS_KEY" { 62 t.Fatalf("Incorrect Access Key Id was populated") 63 } 64 if credentials.SecretAccessKey != "SECRET_KEY" { 65 t.Fatalf("Incorrect Secret Access Key was populated") 66 } 67 } 68 69 func TestBackend(t *testing.T) { 70 testACC(t) 71 72 bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix()) 73 keyName := "testState" 74 75 b := backend.TestBackendConfig(t, New(), map[string]interface{}{ 76 "bucket": bucketName, 77 "key": keyName, 78 "encrypt": true, 79 }).(*Backend) 80 81 createS3Bucket(t, b.s3Client, bucketName) 82 defer deleteS3Bucket(t, b.s3Client, bucketName) 83 84 backend.TestBackend(t, b, nil) 85 } 86 87 func TestBackendLocked(t *testing.T) { 88 testACC(t) 89 90 bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix()) 91 keyName := "testState" 92 93 b1 := backend.TestBackendConfig(t, New(), map[string]interface{}{ 94 "bucket": bucketName, 95 "key": keyName, 96 "encrypt": true, 97 "lock_table": bucketName, 98 }).(*Backend) 99 100 b2 := backend.TestBackendConfig(t, New(), map[string]interface{}{ 101 "bucket": bucketName, 102 "key": keyName, 103 "encrypt": true, 104 "lock_table": bucketName, 105 }).(*Backend) 106 107 createS3Bucket(t, b1.s3Client, bucketName) 108 defer deleteS3Bucket(t, b1.s3Client, bucketName) 109 createDynamoDBTable(t, b1.dynClient, bucketName) 110 defer deleteDynamoDBTable(t, b1.dynClient, bucketName) 111 112 backend.TestBackend(t, b1, b2) 113 } 114 115 func createS3Bucket(t *testing.T, s3Client *s3.S3, bucketName string) { 116 createBucketReq := &s3.CreateBucketInput{ 117 Bucket: &bucketName, 118 } 119 120 // Be clear about what we're doing in case the user needs to clean 121 // this up later. 122 t.Logf("creating S3 bucket %s in %s", bucketName, *s3Client.Config.Region) 123 _, err := s3Client.CreateBucket(createBucketReq) 124 if err != nil { 125 t.Fatal("failed to create test S3 bucket:", err) 126 } 127 } 128 129 func deleteS3Bucket(t *testing.T, s3Client *s3.S3, bucketName string) { 130 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)" 131 132 // first we have to get rid of the env objects, or we can't delete the bucket 133 resp, err := s3Client.ListObjects(&s3.ListObjectsInput{Bucket: &bucketName}) 134 if err != nil { 135 t.Logf(warning, err) 136 return 137 } 138 for _, obj := range resp.Contents { 139 if _, err := s3Client.DeleteObject(&s3.DeleteObjectInput{Bucket: &bucketName, Key: obj.Key}); err != nil { 140 // this will need cleanup no matter what, so just warn and exit 141 t.Logf(warning, err) 142 return 143 } 144 } 145 146 if _, err := s3Client.DeleteBucket(&s3.DeleteBucketInput{Bucket: &bucketName}); err != nil { 147 t.Logf(warning, err) 148 } 149 } 150 151 // create the dynamoDB table, and wait until we can query it. 152 func createDynamoDBTable(t *testing.T, dynClient *dynamodb.DynamoDB, tableName string) { 153 createInput := &dynamodb.CreateTableInput{ 154 AttributeDefinitions: []*dynamodb.AttributeDefinition{ 155 { 156 AttributeName: aws.String("LockID"), 157 AttributeType: aws.String("S"), 158 }, 159 }, 160 KeySchema: []*dynamodb.KeySchemaElement{ 161 { 162 AttributeName: aws.String("LockID"), 163 KeyType: aws.String("HASH"), 164 }, 165 }, 166 ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ 167 ReadCapacityUnits: aws.Int64(5), 168 WriteCapacityUnits: aws.Int64(5), 169 }, 170 TableName: aws.String(tableName), 171 } 172 173 _, err := dynClient.CreateTable(createInput) 174 if err != nil { 175 t.Fatal(err) 176 } 177 178 // now wait until it's ACTIVE 179 start := time.Now() 180 time.Sleep(time.Second) 181 182 describeInput := &dynamodb.DescribeTableInput{ 183 TableName: aws.String(tableName), 184 } 185 186 for { 187 resp, err := dynClient.DescribeTable(describeInput) 188 if err != nil { 189 t.Fatal(err) 190 } 191 192 if *resp.Table.TableStatus == "ACTIVE" { 193 return 194 } 195 196 if time.Since(start) > time.Minute { 197 t.Fatalf("timed out creating DynamoDB table %s", tableName) 198 } 199 200 time.Sleep(3 * time.Second) 201 } 202 203 } 204 205 func deleteDynamoDBTable(t *testing.T, dynClient *dynamodb.DynamoDB, tableName string) { 206 params := &dynamodb.DeleteTableInput{ 207 TableName: aws.String(tableName), 208 } 209 _, err := dynClient.DeleteTable(params) 210 if err != nil { 211 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) 212 } 213 }