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  }