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