239 lines
5.9 KiB
Go
239 lines
5.9 KiB
Go
package remote
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/service/dynamodb"
|
|
"github.com/aws/aws-sdk-go/service/s3"
|
|
)
|
|
|
|
func TestS3Client_impl(t *testing.T) {
|
|
var _ Client = new(S3Client)
|
|
var _ ClientLocker = new(S3Client)
|
|
}
|
|
|
|
func TestS3Factory(t *testing.T) {
|
|
// This test just instantiates the client. Shouldn't make any actual
|
|
// requests nor incur any costs.
|
|
|
|
config := make(map[string]string)
|
|
|
|
// Empty config is an error
|
|
_, err := s3Factory(config)
|
|
if err == nil {
|
|
t.Fatalf("Empty config should be error")
|
|
}
|
|
|
|
config["region"] = "us-west-1"
|
|
config["bucket"] = "foo"
|
|
config["key"] = "bar"
|
|
config["encrypt"] = "1"
|
|
|
|
// For this test we'll provide the credentials as config. The
|
|
// acceptance tests implicitly test passing credentials as
|
|
// environment variables.
|
|
config["access_key"] = "bazkey"
|
|
config["secret_key"] = "bazsecret"
|
|
|
|
client, err := s3Factory(config)
|
|
if err != nil {
|
|
t.Fatalf("Error for valid config")
|
|
}
|
|
|
|
s3Client := client.(*S3Client)
|
|
|
|
if *s3Client.nativeClient.Config.Region != "us-west-1" {
|
|
t.Fatalf("Incorrect region was populated")
|
|
}
|
|
if s3Client.bucketName != "foo" {
|
|
t.Fatalf("Incorrect bucketName was populated")
|
|
}
|
|
if s3Client.keyName != "bar" {
|
|
t.Fatalf("Incorrect keyName was populated")
|
|
}
|
|
|
|
credentials, err := s3Client.nativeClient.Config.Credentials.Get()
|
|
if err != nil {
|
|
t.Fatalf("Error when requesting credentials")
|
|
}
|
|
if credentials.AccessKeyID != "bazkey" {
|
|
t.Fatalf("Incorrect Access Key Id was populated")
|
|
}
|
|
if credentials.SecretAccessKey != "bazsecret" {
|
|
t.Fatalf("Incorrect Secret Access Key was populated")
|
|
}
|
|
}
|
|
|
|
func TestS3Client(t *testing.T) {
|
|
// This test creates a bucket in S3 and populates it.
|
|
// It may incur costs, so it will only run if AWS credential environment
|
|
// variables are present.
|
|
|
|
accessKeyId := os.Getenv("AWS_ACCESS_KEY_ID")
|
|
if accessKeyId == "" {
|
|
t.Skipf("skipping; AWS_ACCESS_KEY_ID must be set")
|
|
}
|
|
|
|
regionName := os.Getenv("AWS_DEFAULT_REGION")
|
|
if regionName == "" {
|
|
regionName = "us-west-2"
|
|
}
|
|
|
|
bucketName := fmt.Sprintf("terraform-remote-s3-test-%x", time.Now().Unix())
|
|
keyName := "testState"
|
|
testData := []byte(`testing data`)
|
|
|
|
config := make(map[string]string)
|
|
config["region"] = regionName
|
|
config["bucket"] = bucketName
|
|
config["key"] = keyName
|
|
config["encrypt"] = "1"
|
|
|
|
client, err := s3Factory(config)
|
|
if err != nil {
|
|
t.Fatalf("Error for valid config")
|
|
}
|
|
|
|
s3Client := client.(*S3Client)
|
|
nativeClient := s3Client.nativeClient
|
|
|
|
createBucketReq := &s3.CreateBucketInput{
|
|
Bucket: &bucketName,
|
|
}
|
|
|
|
// Be clear about what we're doing in case the user needs to clean
|
|
// this up later.
|
|
t.Logf("Creating S3 bucket %s in %s", bucketName, regionName)
|
|
_, err = nativeClient.CreateBucket(createBucketReq)
|
|
if err != nil {
|
|
t.Skipf("Failed to create test S3 bucket, so skipping")
|
|
}
|
|
|
|
// Ensure we can perform a PUT request with the encryption header
|
|
err = s3Client.Put(testData)
|
|
if err != nil {
|
|
t.Logf("WARNING: Failed to send test data to S3 bucket. (error was %s)", err)
|
|
}
|
|
|
|
defer func() {
|
|
deleteBucketReq := &s3.DeleteBucketInput{
|
|
Bucket: &bucketName,
|
|
}
|
|
|
|
_, err := nativeClient.DeleteBucket(deleteBucketReq)
|
|
if err != nil {
|
|
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)
|
|
}
|
|
}()
|
|
|
|
testClient(t, client)
|
|
}
|
|
|
|
func TestS3ClientLocks(t *testing.T) {
|
|
// This test creates a DynamoDB table.
|
|
// It may incur costs, so it will only run if AWS credential environment
|
|
// variables are present.
|
|
|
|
accessKeyId := os.Getenv("AWS_ACCESS_KEY_ID")
|
|
if accessKeyId == "" {
|
|
t.Skipf("skipping; AWS_ACCESS_KEY_ID must be set")
|
|
}
|
|
|
|
regionName := os.Getenv("AWS_DEFAULT_REGION")
|
|
if regionName == "" {
|
|
regionName = "us-west-2"
|
|
}
|
|
|
|
bucketName := fmt.Sprintf("terraform-remote-s3-lock-%x", time.Now().Unix())
|
|
keyName := "testState"
|
|
|
|
config := make(map[string]string)
|
|
config["region"] = regionName
|
|
config["bucket"] = bucketName
|
|
config["key"] = keyName
|
|
config["encrypt"] = "1"
|
|
config["lock_table"] = bucketName
|
|
|
|
client, err := s3Factory(config)
|
|
if err != nil {
|
|
t.Fatalf("Error for valid config")
|
|
}
|
|
|
|
s3Client := client.(*S3Client)
|
|
|
|
// set this up before we try to crate the table, in case we timeout creating it.
|
|
defer deleteDynaboDBTable(t, s3Client, bucketName)
|
|
|
|
createDynamoDBTable(t, s3Client, bucketName)
|
|
|
|
TestRemoteLocks(t, client, client)
|
|
}
|
|
|
|
// create the dynamoDB table, and wait until we can query it.
|
|
func createDynamoDBTable(t *testing.T, c *S3Client, tableName string) {
|
|
createInput := &dynamodb.CreateTableInput{
|
|
AttributeDefinitions: []*dynamodb.AttributeDefinition{
|
|
{
|
|
AttributeName: aws.String("LockID"),
|
|
AttributeType: aws.String("S"),
|
|
},
|
|
},
|
|
KeySchema: []*dynamodb.KeySchemaElement{
|
|
{
|
|
AttributeName: aws.String("LockID"),
|
|
KeyType: aws.String("HASH"),
|
|
},
|
|
},
|
|
ProvisionedThroughput: &dynamodb.ProvisionedThroughput{
|
|
ReadCapacityUnits: aws.Int64(5),
|
|
WriteCapacityUnits: aws.Int64(5),
|
|
},
|
|
TableName: aws.String(tableName),
|
|
}
|
|
|
|
_, err := c.dynClient.CreateTable(createInput)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// now wait until it's ACTIVE
|
|
start := time.Now()
|
|
time.Sleep(time.Second)
|
|
|
|
describeInput := &dynamodb.DescribeTableInput{
|
|
TableName: aws.String(tableName),
|
|
}
|
|
|
|
for {
|
|
resp, err := c.dynClient.DescribeTable(describeInput)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if *resp.Table.TableStatus == "ACTIVE" {
|
|
return
|
|
}
|
|
|
|
if time.Since(start) > time.Minute {
|
|
t.Fatalf("timed out creating DynamoDB table %s", tableName)
|
|
}
|
|
|
|
time.Sleep(3 * time.Second)
|
|
}
|
|
|
|
}
|
|
|
|
func deleteDynaboDBTable(t *testing.T, c *S3Client, tableName string) {
|
|
params := &dynamodb.DeleteTableInput{
|
|
TableName: aws.String(tableName),
|
|
}
|
|
_, err := c.dynClient.DeleteTable(params)
|
|
if err != nil {
|
|
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)
|
|
}
|
|
}
|