github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/state/remote/s3_test.go (about) 1 package remote 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 ) 13 14 func TestS3Client_impl(t *testing.T) { 15 var _ Client = new(S3Client) 16 } 17 18 func TestS3Factory(t *testing.T) { 19 // This test just instantiates the client. Shouldn't make any actual 20 // requests nor incur any costs. 21 22 config := make(map[string]string) 23 24 // Empty config is an error 25 _, err := s3Factory(config) 26 if err == nil { 27 t.Fatalf("Empty config should be error") 28 } 29 30 config["region"] = "us-west-1" 31 config["bucket"] = "foo" 32 config["key"] = "bar" 33 config["encrypt"] = "1" 34 35 // For this test we'll provide the credentials as config. The 36 // acceptance tests implicitly test passing credentials as 37 // environment variables. 38 config["access_key"] = "bazkey" 39 config["secret_key"] = "bazsecret" 40 41 client, err := s3Factory(config) 42 if err != nil { 43 t.Fatalf("Error for valid config") 44 } 45 46 s3Client := client.(*S3Client) 47 48 if *s3Client.nativeClient.Config.Region != "us-west-1" { 49 t.Fatalf("Incorrect region was populated") 50 } 51 if s3Client.bucketName != "foo" { 52 t.Fatalf("Incorrect bucketName was populated") 53 } 54 if s3Client.keyName != "bar" { 55 t.Fatalf("Incorrect keyName was populated") 56 } 57 58 credentials, err := s3Client.nativeClient.Config.Credentials.Get() 59 if err != nil { 60 t.Fatalf("Error when requesting credentials") 61 } 62 if credentials.AccessKeyID != "bazkey" { 63 t.Fatalf("Incorrect Access Key Id was populated") 64 } 65 if credentials.SecretAccessKey != "bazsecret" { 66 t.Fatalf("Incorrect Secret Access Key was populated") 67 } 68 } 69 70 func TestS3Client(t *testing.T) { 71 // This test creates a bucket in S3 and populates it. 72 // It may incur costs, so it will only run if AWS credential environment 73 // variables are present. 74 75 accessKeyId := os.Getenv("AWS_ACCESS_KEY_ID") 76 if accessKeyId == "" { 77 t.Skipf("skipping; AWS_ACCESS_KEY_ID must be set") 78 } 79 80 regionName := os.Getenv("AWS_DEFAULT_REGION") 81 if regionName == "" { 82 regionName = "us-west-2" 83 } 84 85 bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix()) 86 keyName := "testState" 87 testData := []byte(`testing data`) 88 89 config := make(map[string]string) 90 config["region"] = regionName 91 config["bucket"] = bucketName 92 config["key"] = keyName 93 config["encrypt"] = "1" 94 95 client, err := s3Factory(config) 96 if err != nil { 97 t.Fatalf("Error for valid config") 98 } 99 100 s3Client := client.(*S3Client) 101 nativeClient := s3Client.nativeClient 102 103 createBucketReq := &s3.CreateBucketInput{ 104 Bucket: &bucketName, 105 } 106 107 // Be clear about what we're doing in case the user needs to clean 108 // this up later. 109 t.Logf("Creating S3 bucket %s in %s", bucketName, regionName) 110 _, err = nativeClient.CreateBucket(createBucketReq) 111 if err != nil { 112 t.Skipf("Failed to create test S3 bucket, so skipping") 113 } 114 115 // Ensure we can perform a PUT request with the encryption header 116 err = s3Client.Put(testData) 117 if err != nil { 118 t.Logf("WARNING: Failed to send test data to S3 bucket. (error was %s)", err) 119 } 120 121 defer func() { 122 deleteBucketReq := &s3.DeleteBucketInput{ 123 Bucket: &bucketName, 124 } 125 126 _, err := nativeClient.DeleteBucket(deleteBucketReq) 127 if err != nil { 128 t.Logf("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)", err) 129 } 130 }() 131 132 testClient(t, client) 133 } 134 135 func TestS3ClientLocks(t *testing.T) { 136 // This test creates a DynamoDB table. 137 // It may incur costs, so it will only run if AWS credential environment 138 // variables are present. 139 140 accessKeyId := os.Getenv("AWS_ACCESS_KEY_ID") 141 if accessKeyId == "" { 142 t.Skipf("skipping; AWS_ACCESS_KEY_ID must be set") 143 } 144 145 regionName := os.Getenv("AWS_DEFAULT_REGION") 146 if regionName == "" { 147 regionName = "us-west-2" 148 } 149 150 bucketName := fmt.Sprintf("terraform-remote-s3-lock-%x", time.Now().Unix()) 151 keyName := "testState" 152 153 config := make(map[string]string) 154 config["region"] = regionName 155 config["bucket"] = bucketName 156 config["key"] = keyName 157 config["encrypt"] = "1" 158 config["lock_table"] = bucketName 159 160 client, err := s3Factory(config) 161 if err != nil { 162 t.Fatalf("Error for valid config") 163 } 164 165 s3Client := client.(*S3Client) 166 167 // set this up before we try to crate the table, in case we timeout creating it. 168 defer deleteDynaboDBTable(t, s3Client, bucketName) 169 170 createDynamoDBTable(t, s3Client, bucketName) 171 172 TestRemoteLocks(t, client, client) 173 } 174 175 // create the dynamoDB table, and wait until we can query it. 176 func createDynamoDBTable(t *testing.T, c *S3Client, tableName string) { 177 createInput := &dynamodb.CreateTableInput{ 178 AttributeDefinitions: []*dynamodb.AttributeDefinition{ 179 { 180 AttributeName: aws.String("LockID"), 181 AttributeType: aws.String("S"), 182 }, 183 }, 184 KeySchema: []*dynamodb.KeySchemaElement{ 185 { 186 AttributeName: aws.String("LockID"), 187 KeyType: aws.String("HASH"), 188 }, 189 }, 190 ProvisionedThroughput: &dynamodb.ProvisionedThroughput{ 191 ReadCapacityUnits: aws.Int64(5), 192 WriteCapacityUnits: aws.Int64(5), 193 }, 194 TableName: aws.String(tableName), 195 } 196 197 _, err := c.dynClient.CreateTable(createInput) 198 if err != nil { 199 t.Fatal(err) 200 } 201 202 // now wait until it's ACTIVE 203 start := time.Now() 204 time.Sleep(time.Second) 205 206 describeInput := &dynamodb.DescribeTableInput{ 207 TableName: aws.String(tableName), 208 } 209 210 for { 211 resp, err := c.dynClient.DescribeTable(describeInput) 212 if err != nil { 213 t.Fatal(err) 214 } 215 216 if *resp.Table.TableStatus == "ACTIVE" { 217 return 218 } 219 220 if time.Since(start) > time.Minute { 221 t.Fatalf("timed out creating DynamoDB table %s", tableName) 222 } 223 224 time.Sleep(3 * time.Second) 225 } 226 227 } 228 229 func deleteDynaboDBTable(t *testing.T, c *S3Client, tableName string) { 230 params := &dynamodb.DeleteTableInput{ 231 TableName: aws.String(tableName), 232 } 233 _, err := c.dynClient.DeleteTable(params) 234 if err != nil { 235 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) 236 } 237 }