From 1669c35007f5c20fc156766456a5e1b593766868 Mon Sep 17 00:00:00 2001 From: John Ewart Date: Wed, 3 Jun 2015 17:05:40 -0700 Subject: [PATCH] Adding DynamoDB acceptance tests --- .../aws/resource_aws_dynamodb_table_test.go | 296 ++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 builtin/providers/aws/resource_aws_dynamodb_table_test.go diff --git a/builtin/providers/aws/resource_aws_dynamodb_table_test.go b/builtin/providers/aws/resource_aws_dynamodb_table_test.go new file mode 100644 index 000000000..149f36a55 --- /dev/null +++ b/builtin/providers/aws/resource_aws_dynamodb_table_test.go @@ -0,0 +1,296 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/awslabs/aws-sdk-go/aws" + "github.com/awslabs/aws-sdk-go/aws/awserr" + "github.com/awslabs/aws-sdk-go/service/dynamodb" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSDynamoDbTable(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSDynamoDbTableDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSDynamoDbConfigInitialState, + Check: resource.ComposeTestCheckFunc( + testAccCheckInitialAWSDynamoDbTableExists("aws_dynamodb_table.basic-dynamodb-table"), + ), + }, + resource.TestStep{ + Config: testAccAWSDynamoDbConfigAddSecondaryGSI, + Check: resource.ComposeTestCheckFunc( + testAccCheckDynamoDbTableWasUpdated("aws_dynamodb_table.basic-dynamodb-table"), + ), + }, + }, + }) +} + +func testAccCheckAWSDynamoDbTableDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).dynamodbconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_dynamodb_table" { + continue + } + + fmt.Printf("[DEBUG] Checking if DynamoDB table %s exists", rs.Primary.ID) + // Check if queue exists by checking for its attributes + params := &dynamodb.DescribeTableInput{ + TableName: aws.String(rs.Primary.ID), + } + _, err := conn.DescribeTable(params) + if err == nil { + return fmt.Errorf("DynamoDB table %s still exists. Failing!", rs.Primary.ID) + } + + // Verify the error is what we want + _, ok := err.(awserr.Error) + if !ok { + return err + } + } + + return nil +} + +func testAccCheckInitialAWSDynamoDbTableExists(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + fmt.Printf("[DEBUG] Trying to create initial table state!") + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No DynamoDB table name specified!") + } + + conn := testAccProvider.Meta().(*AWSClient).dynamodbconn + + params := &dynamodb.DescribeTableInput{ + TableName: aws.String(rs.Primary.ID), + } + + resp, err := conn.DescribeTable(params) + + if err != nil { + fmt.Printf("[ERROR] Problem describing table '%s': %s", rs.Primary.ID, err) + return err + } + + table := resp.Table + + fmt.Printf("[DEBUG] Checking on table %s", rs.Primary.ID) + + if *table.ProvisionedThroughput.WriteCapacityUnits != 20 { + return fmt.Errorf("Provisioned write capacity was %d, not 20!", table.ProvisionedThroughput.WriteCapacityUnits) + } + + if *table.ProvisionedThroughput.ReadCapacityUnits != 10 { + return fmt.Errorf("Provisioned read capacity was %d, not 10!", table.ProvisionedThroughput.ReadCapacityUnits) + } + + attrCount := len(table.AttributeDefinitions) + gsiCount := len(table.GlobalSecondaryIndexes) + lsiCount := len(table.LocalSecondaryIndexes) + + if attrCount != 4 { + return fmt.Errorf("There were %d attributes, not 4 like there should have been!", attrCount) + } + + if gsiCount != 1 { + return fmt.Errorf("There were %d GSIs, not 1 like there should have been!", gsiCount) + } + + if lsiCount != 1 { + return fmt.Errorf("There were %d LSIs, not 1 like there should have been!", lsiCount) + } + + attrmap := dynamoDbAttributesToMap(&table.AttributeDefinitions) + if attrmap["TestTableHashKey"] != "S" { + return fmt.Errorf("Test table hash key was of type %s instead of S!", attrmap["TestTableHashKey"]) + } + if attrmap["TestTableRangeKey"] != "S" { + return fmt.Errorf("Test table range key was of type %s instead of S!", attrmap["TestTableRangeKey"]) + } + if attrmap["TestLSIRangeKey"] != "N" { + return fmt.Errorf("Test table LSI range key was of type %s instead of N!", attrmap["TestLSIRangeKey"]) + } + if attrmap["TestGSIRangeKey"] != "S" { + return fmt.Errorf("Test table GSI range key was of type %s instead of S!", attrmap["TestGSIRangeKey"]) + } + + return nil + } +} + +func testAccCheckDynamoDbTableWasUpdated(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Not found: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("No DynamoDB table name specified!") + } + + conn := testAccProvider.Meta().(*AWSClient).dynamodbconn + + params := &dynamodb.DescribeTableInput{ + TableName: aws.String(rs.Primary.ID), + } + resp, err := conn.DescribeTable(params) + table := resp.Table + + if err != nil { + return err + } + + attrCount := len(table.AttributeDefinitions) + gsiCount := len(table.GlobalSecondaryIndexes) + lsiCount := len(table.LocalSecondaryIndexes) + + if attrCount != 4 { + return fmt.Errorf("There were %d attributes, not 4 like there should have been!", attrCount) + } + + if gsiCount != 1 { + return fmt.Errorf("There were %d GSIs, not 1 like there should have been!", gsiCount) + } + + if lsiCount != 1 { + return fmt.Errorf("There were %d LSIs, not 1 like there should have been!", lsiCount) + } + + if dynamoDbGetGSIIndex(&table.GlobalSecondaryIndexes, "ReplacementTestTableGSI") == -1 { + return fmt.Errorf("Could not find GSI named 'ReplacementTestTableGSI' in the table!") + } + + if dynamoDbGetGSIIndex(&table.GlobalSecondaryIndexes, "InitialTestTableGSI") != -1 { + return fmt.Errorf("Should have removed 'InitialTestTableGSI' but it still exists!") + } + + attrmap := dynamoDbAttributesToMap(&table.AttributeDefinitions) + if attrmap["TestTableHashKey"] != "S" { + return fmt.Errorf("Test table hash key was of type %s instead of S!", attrmap["TestTableHashKey"]) + } + if attrmap["TestTableRangeKey"] != "S" { + return fmt.Errorf("Test table range key was of type %s instead of S!", attrmap["TestTableRangeKey"]) + } + if attrmap["TestLSIRangeKey"] != "N" { + return fmt.Errorf("Test table LSI range key was of type %s instead of N!", attrmap["TestLSIRangeKey"]) + } + if attrmap["ReplacementGSIRangeKey"] != "N" { + return fmt.Errorf("Test table replacement GSI range key was of type %s instead of N!", attrmap["ReplacementGSIRangeKey"]) + } + + return nil + } +} + +func dynamoDbGetGSIIndex(gsiList *[]*dynamodb.GlobalSecondaryIndexDescription, target string) int { + for idx, gsiObject := range *gsiList { + if *gsiObject.IndexName == target { + return idx + } + } + + return -1 +} + +func dynamoDbAttributesToMap(attributes *[]*dynamodb.AttributeDefinition) map[string]string { + attrmap := make(map[string]string) + + for _, attrdef := range *attributes { + attrmap[*(attrdef.AttributeName)] = *(attrdef.AttributeType) + } + + return attrmap +} + +const testAccAWSDynamoDbConfigInitialState = ` +resource "aws_dynamodb_table" "basic-dynamodb-table" { + name = "TerraformTestTable" + read_capacity = 10 + write_capacity = 20 + hash_key = "TestTableHashKey" + range_key = "TestTableRangeKey" + attribute { + name = "TestTableHashKey" + type = "S" + } + attribute { + name = "TestTableRangeKey" + type = "S" + } + attribute { + name = "TestLSIRangeKey" + type = "N" + } + attribute { + name = "TestGSIRangeKey" + type = "S" + } + local_secondary_index { + name = "TestTableLSI" + range_key = "TestLSIRangeKey" + projection_type = "ALL" + } + global_secondary_index { + name = "InitialTestTableGSI" + hash_key = "TestTableHashKey" + range_key = "TestGSIRangeKey" + write_capacity = 10 + read_capacity = 10 + projection_type = "ALL" + } +} +` + +const testAccAWSDynamoDbConfigAddSecondaryGSI = ` +resource "aws_dynamodb_table" "basic-dynamodb-table" { + name = "TerraformTestTable" + read_capacity = 20 + write_capacity = 20 + hash_key = "TestTableHashKey" + range_key = "TestTableRangeKey" + attribute { + name = "TestTableHashKey" + type = "S" + } + attribute { + name = "TestTableRangeKey" + type = "S" + } + attribute { + name = "TestLSIRangeKey" + type = "N" + } + attribute { + name = "ReplacementGSIRangeKey" + type = "N" + } + local_secondary_index { + name = "TestTableLSI" + range_key = "TestLSIRangeKey" + projection_type = "ALL" + } + global_secondary_index { + name = "ReplacementTestTableGSI" + hash_key = "TestTableHashKey" + range_key = "ReplacementGSIRangeKey" + write_capacity = 5 + read_capacity = 5 + projection_type = "ALL" + } +} +`