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 }