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