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