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 }