github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/resource_aws_dynamodb_table_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"testing"
     7  
     8  	"github.com/aws/aws-sdk-go/aws"
     9  	"github.com/aws/aws-sdk-go/aws/awserr"
    10  	"github.com/aws/aws-sdk-go/service/dynamodb"
    11  	"github.com/hashicorp/terraform/helper/acctest"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/terraform"
    14  )
    15  
    16  func TestAccAWSDynamoDbTable_basic(t *testing.T) {
    17  	resource.Test(t, resource.TestCase{
    18  		PreCheck:     func() { testAccPreCheck(t) },
    19  		Providers:    testAccProviders,
    20  		CheckDestroy: testAccCheckAWSDynamoDbTableDestroy,
    21  		Steps: []resource.TestStep{
    22  			resource.TestStep{
    23  				Config: testAccAWSDynamoDbConfigInitialState(),
    24  				Check: resource.ComposeTestCheckFunc(
    25  					testAccCheckInitialAWSDynamoDbTableExists("aws_dynamodb_table.basic-dynamodb-table"),
    26  				),
    27  			},
    28  			resource.TestStep{
    29  				Config: testAccAWSDynamoDbConfigAddSecondaryGSI,
    30  				Check: resource.ComposeTestCheckFunc(
    31  					testAccCheckDynamoDbTableWasUpdated("aws_dynamodb_table.basic-dynamodb-table"),
    32  				),
    33  			},
    34  		},
    35  	})
    36  }
    37  
    38  func TestAccAWSDynamoDbTable_streamSpecification(t *testing.T) {
    39  	resource.Test(t, resource.TestCase{
    40  		PreCheck:     func() { testAccPreCheck(t) },
    41  		Providers:    testAccProviders,
    42  		CheckDestroy: testAccCheckAWSDynamoDbTableDestroy,
    43  		Steps: []resource.TestStep{
    44  			resource.TestStep{
    45  				Config: testAccAWSDynamoDbConfigStreamSpecification(),
    46  				Check: resource.ComposeTestCheckFunc(
    47  					testAccCheckInitialAWSDynamoDbTableExists("aws_dynamodb_table.basic-dynamodb-table"),
    48  					resource.TestCheckResourceAttr(
    49  						"aws_dynamodb_table.basic-dynamodb-table", "stream_enabled", "true"),
    50  					resource.TestCheckResourceAttr(
    51  						"aws_dynamodb_table.basic-dynamodb-table", "stream_view_type", "KEYS_ONLY"),
    52  				),
    53  			},
    54  		},
    55  	})
    56  }
    57  
    58  func TestResourceAWSDynamoDbTableStreamViewType_validation(t *testing.T) {
    59  	cases := []struct {
    60  		Value    string
    61  		ErrCount int
    62  	}{
    63  		{
    64  			Value:    "KEYS-ONLY",
    65  			ErrCount: 1,
    66  		},
    67  		{
    68  			Value:    "RANDOM-STRING",
    69  			ErrCount: 1,
    70  		},
    71  		{
    72  			Value:    "KEYS_ONLY",
    73  			ErrCount: 0,
    74  		},
    75  		{
    76  			Value:    "NEW_AND_OLD_IMAGES",
    77  			ErrCount: 0,
    78  		},
    79  		{
    80  			Value:    "NEW_IMAGE",
    81  			ErrCount: 0,
    82  		},
    83  		{
    84  			Value:    "OLD_IMAGE",
    85  			ErrCount: 0,
    86  		},
    87  	}
    88  
    89  	for _, tc := range cases {
    90  		_, errors := validateStreamViewType(tc.Value, "aws_dynamodb_table_stream_view_type")
    91  
    92  		if len(errors) != tc.ErrCount {
    93  			t.Fatalf("Expected the DynamoDB stream_view_type to trigger a validation error")
    94  		}
    95  	}
    96  }
    97  
    98  func testAccCheckAWSDynamoDbTableDestroy(s *terraform.State) error {
    99  	conn := testAccProvider.Meta().(*AWSClient).dynamodbconn
   100  
   101  	for _, rs := range s.RootModule().Resources {
   102  		if rs.Type != "aws_dynamodb_table" {
   103  			continue
   104  		}
   105  
   106  		log.Printf("[DEBUG] Checking if DynamoDB table %s exists", rs.Primary.ID)
   107  		// Check if queue exists by checking for its attributes
   108  		params := &dynamodb.DescribeTableInput{
   109  			TableName: aws.String(rs.Primary.ID),
   110  		}
   111  
   112  		_, err := conn.DescribeTable(params)
   113  		if err == nil {
   114  			return fmt.Errorf("DynamoDB table %s still exists. Failing!", rs.Primary.ID)
   115  		}
   116  
   117  		// Verify the error is what we want
   118  		if dbErr, ok := err.(awserr.Error); ok && dbErr.Code() == "ResourceNotFoundException" {
   119  			return nil
   120  		}
   121  
   122  		return err
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func testAccCheckInitialAWSDynamoDbTableExists(n string) resource.TestCheckFunc {
   129  	return func(s *terraform.State) error {
   130  		fmt.Printf("[DEBUG] Trying to create initial table state!")
   131  		rs, ok := s.RootModule().Resources[n]
   132  		if !ok {
   133  			return fmt.Errorf("Not found: %s", n)
   134  		}
   135  
   136  		if rs.Primary.ID == "" {
   137  			return fmt.Errorf("No DynamoDB table name specified!")
   138  		}
   139  
   140  		conn := testAccProvider.Meta().(*AWSClient).dynamodbconn
   141  
   142  		params := &dynamodb.DescribeTableInput{
   143  			TableName: aws.String(rs.Primary.ID),
   144  		}
   145  
   146  		resp, err := conn.DescribeTable(params)
   147  
   148  		if err != nil {
   149  			fmt.Printf("[ERROR] Problem describing table '%s': %s", rs.Primary.ID, err)
   150  			return err
   151  		}
   152  
   153  		table := resp.Table
   154  
   155  		fmt.Printf("[DEBUG] Checking on table %s", rs.Primary.ID)
   156  
   157  		if *table.ProvisionedThroughput.WriteCapacityUnits != 20 {
   158  			return fmt.Errorf("Provisioned write capacity was %d, not 20!", table.ProvisionedThroughput.WriteCapacityUnits)
   159  		}
   160  
   161  		if *table.ProvisionedThroughput.ReadCapacityUnits != 10 {
   162  			return fmt.Errorf("Provisioned read capacity was %d, not 10!", table.ProvisionedThroughput.ReadCapacityUnits)
   163  		}
   164  
   165  		attrCount := len(table.AttributeDefinitions)
   166  		gsiCount := len(table.GlobalSecondaryIndexes)
   167  		lsiCount := len(table.LocalSecondaryIndexes)
   168  
   169  		if attrCount != 4 {
   170  			return fmt.Errorf("There were %d attributes, not 4 like there should have been!", attrCount)
   171  		}
   172  
   173  		if gsiCount != 1 {
   174  			return fmt.Errorf("There were %d GSIs, not 1 like there should have been!", gsiCount)
   175  		}
   176  
   177  		if lsiCount != 1 {
   178  			return fmt.Errorf("There were %d LSIs, not 1 like there should have been!", lsiCount)
   179  		}
   180  
   181  		attrmap := dynamoDbAttributesToMap(&table.AttributeDefinitions)
   182  		if attrmap["TestTableHashKey"] != "S" {
   183  			return fmt.Errorf("Test table hash key was of type %s instead of S!", attrmap["TestTableHashKey"])
   184  		}
   185  		if attrmap["TestTableRangeKey"] != "S" {
   186  			return fmt.Errorf("Test table range key was of type %s instead of S!", attrmap["TestTableRangeKey"])
   187  		}
   188  		if attrmap["TestLSIRangeKey"] != "N" {
   189  			return fmt.Errorf("Test table LSI range key was of type %s instead of N!", attrmap["TestLSIRangeKey"])
   190  		}
   191  		if attrmap["TestGSIRangeKey"] != "S" {
   192  			return fmt.Errorf("Test table GSI range key was of type %s instead of S!", attrmap["TestGSIRangeKey"])
   193  		}
   194  
   195  		return nil
   196  	}
   197  }
   198  
   199  func testAccCheckDynamoDbTableWasUpdated(n string) resource.TestCheckFunc {
   200  	return func(s *terraform.State) error {
   201  		rs, ok := s.RootModule().Resources[n]
   202  		if !ok {
   203  			return fmt.Errorf("Not found: %s", n)
   204  		}
   205  
   206  		if rs.Primary.ID == "" {
   207  			return fmt.Errorf("No DynamoDB table name specified!")
   208  		}
   209  
   210  		conn := testAccProvider.Meta().(*AWSClient).dynamodbconn
   211  
   212  		params := &dynamodb.DescribeTableInput{
   213  			TableName: aws.String(rs.Primary.ID),
   214  		}
   215  		resp, err := conn.DescribeTable(params)
   216  		table := resp.Table
   217  
   218  		if err != nil {
   219  			return err
   220  		}
   221  
   222  		attrCount := len(table.AttributeDefinitions)
   223  		gsiCount := len(table.GlobalSecondaryIndexes)
   224  		lsiCount := len(table.LocalSecondaryIndexes)
   225  
   226  		if attrCount != 4 {
   227  			return fmt.Errorf("There were %d attributes, not 4 like there should have been!", attrCount)
   228  		}
   229  
   230  		if gsiCount != 1 {
   231  			return fmt.Errorf("There were %d GSIs, not 1 like there should have been!", gsiCount)
   232  		}
   233  
   234  		if lsiCount != 1 {
   235  			return fmt.Errorf("There were %d LSIs, not 1 like there should have been!", lsiCount)
   236  		}
   237  
   238  		if dynamoDbGetGSIIndex(&table.GlobalSecondaryIndexes, "ReplacementTestTableGSI") == -1 {
   239  			return fmt.Errorf("Could not find GSI named 'ReplacementTestTableGSI' in the table!")
   240  		}
   241  
   242  		if dynamoDbGetGSIIndex(&table.GlobalSecondaryIndexes, "InitialTestTableGSI") != -1 {
   243  			return fmt.Errorf("Should have removed 'InitialTestTableGSI' but it still exists!")
   244  		}
   245  
   246  		attrmap := dynamoDbAttributesToMap(&table.AttributeDefinitions)
   247  		if attrmap["TestTableHashKey"] != "S" {
   248  			return fmt.Errorf("Test table hash key was of type %s instead of S!", attrmap["TestTableHashKey"])
   249  		}
   250  		if attrmap["TestTableRangeKey"] != "S" {
   251  			return fmt.Errorf("Test table range key was of type %s instead of S!", attrmap["TestTableRangeKey"])
   252  		}
   253  		if attrmap["TestLSIRangeKey"] != "N" {
   254  			return fmt.Errorf("Test table LSI range key was of type %s instead of N!", attrmap["TestLSIRangeKey"])
   255  		}
   256  		if attrmap["ReplacementGSIRangeKey"] != "N" {
   257  			return fmt.Errorf("Test table replacement GSI range key was of type %s instead of N!", attrmap["ReplacementGSIRangeKey"])
   258  		}
   259  
   260  		return nil
   261  	}
   262  }
   263  
   264  func dynamoDbGetGSIIndex(gsiList *[]*dynamodb.GlobalSecondaryIndexDescription, target string) int {
   265  	for idx, gsiObject := range *gsiList {
   266  		if *gsiObject.IndexName == target {
   267  			return idx
   268  		}
   269  	}
   270  
   271  	return -1
   272  }
   273  
   274  func dynamoDbAttributesToMap(attributes *[]*dynamodb.AttributeDefinition) map[string]string {
   275  	attrmap := make(map[string]string)
   276  
   277  	for _, attrdef := range *attributes {
   278  		attrmap[*attrdef.AttributeName] = *attrdef.AttributeType
   279  	}
   280  
   281  	return attrmap
   282  }
   283  
   284  func testAccAWSDynamoDbConfigInitialState() string {
   285  	return fmt.Sprintf(`
   286  resource "aws_dynamodb_table" "basic-dynamodb-table" {
   287      name = "TerraformTestTable-%d"
   288  		read_capacity = 10
   289  		write_capacity = 20
   290  		hash_key = "TestTableHashKey"
   291  		range_key = "TestTableRangeKey"
   292  		attribute {
   293  			name = "TestTableHashKey"
   294  			type = "S"
   295  		}
   296  		attribute {
   297  			name = "TestTableRangeKey"
   298  			type = "S"
   299  		}
   300  		attribute {
   301  			name = "TestLSIRangeKey"
   302  			type = "N"
   303  		}
   304  		attribute {
   305  			name = "TestGSIRangeKey"
   306  			type = "S"
   307  		}
   308  		local_secondary_index {
   309  			name = "TestTableLSI"
   310  			range_key = "TestLSIRangeKey"
   311  			projection_type = "ALL"
   312  		}
   313  		global_secondary_index {
   314  			name = "InitialTestTableGSI"
   315  			hash_key = "TestTableHashKey"
   316  			range_key = "TestGSIRangeKey"
   317  			write_capacity = 10
   318  			read_capacity = 10
   319  			projection_type = "KEYS_ONLY"
   320  		}
   321  }
   322  `, acctest.RandInt())
   323  }
   324  
   325  const testAccAWSDynamoDbConfigAddSecondaryGSI = `
   326  resource "aws_dynamodb_table" "basic-dynamodb-table" {
   327      name = "TerraformTestTable"
   328  		read_capacity = 20
   329  		write_capacity = 20
   330  		hash_key = "TestTableHashKey"
   331  		range_key = "TestTableRangeKey"
   332  		attribute {
   333  			name = "TestTableHashKey"
   334  			type = "S"
   335  		}
   336  		attribute {
   337  			name = "TestTableRangeKey"
   338  			type = "S"
   339  		}
   340  		attribute {
   341  			name = "TestLSIRangeKey"
   342  			type = "N"
   343  		}
   344  		attribute {
   345  			name = "ReplacementGSIRangeKey"
   346  			type = "N"
   347  		}
   348  		local_secondary_index {
   349  			name = "TestTableLSI"
   350  			range_key = "TestLSIRangeKey"
   351  			projection_type = "ALL"
   352  		}
   353  		global_secondary_index {
   354  			name = "ReplacementTestTableGSI"
   355  			hash_key = "TestTableHashKey"
   356  			range_key = "ReplacementGSIRangeKey"
   357  			write_capacity = 5
   358  			read_capacity = 5
   359  			projection_type = "INCLUDE"
   360  			non_key_attributes = ["TestNonKeyAttribute"]
   361  		}
   362  }
   363  `
   364  
   365  func testAccAWSDynamoDbConfigStreamSpecification() string {
   366  	return fmt.Sprintf(`
   367  resource "aws_dynamodb_table" "basic-dynamodb-table" {
   368      name = "TerraformTestStreamTable-%d"
   369  	read_capacity = 10
   370  	write_capacity = 20
   371  	hash_key = "TestTableHashKey"
   372  	range_key = "TestTableRangeKey"
   373  	attribute {
   374  		name = "TestTableHashKey"
   375  		type = "S"
   376  	}
   377  	attribute {
   378  		name = "TestTableRangeKey"
   379  		type = "S"
   380  	}
   381  	attribute {
   382  		name = "TestLSIRangeKey"
   383  		type = "N"
   384  	}
   385  	attribute {
   386  		name = "TestGSIRangeKey"
   387  		type = "S"
   388  	}
   389  	local_secondary_index {
   390  		name = "TestTableLSI"
   391  		range_key = "TestLSIRangeKey"
   392  		projection_type = "ALL"
   393  	}
   394  	global_secondary_index {
   395  		name = "InitialTestTableGSI"
   396  		hash_key = "TestTableHashKey"
   397  		range_key = "TestGSIRangeKey"
   398  		write_capacity = 10
   399  		read_capacity = 10
   400  		projection_type = "KEYS_ONLY"
   401  	}
   402  	stream_enabled = true
   403  	stream_view_type = "KEYS_ONLY"
   404  }
   405  `, acctest.RandInt())
   406  }