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