Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for dynamodb billing #6648

Merged
merged 7 commits into from
Nov 30, 2018
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 53 additions & 9 deletions aws/resource_aws_dynamodb_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,22 @@ func resourceAwsDynamoDbTable() *schema.Resource {
Optional: true,
ForceNew: true,
},
"billing_mode": {
bflad marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeString,
Optional: true,
Default: dynamodb.BillingModeProvisioned,
ValidateFunc: validation.StringInSlice([]string{
dynamodb.BillingModePayPerRequest,
dynamodb.BillingModeProvisioned,
}, false),
},
"write_capacity": {
Type: schema.TypeInt,
Required: true,
Optional: true,
},
"read_capacity": {
Type: schema.TypeInt,
Required: true,
Optional: true,
},
"attribute": {
Type: schema.TypeSet,
Expand Down Expand Up @@ -279,12 +288,22 @@ func resourceAwsDynamoDbTableCreate(d *schema.ResourceData, meta interface{}) er
log.Printf("[DEBUG] Creating DynamoDB table with key schema: %#v", keySchemaMap)

req := &dynamodb.CreateTableInput{
TableName: aws.String(d.Get("name").(string)),
ProvisionedThroughput: expandDynamoDbProvisionedThroughput(map[string]interface{}{
"read_capacity": d.Get("read_capacity"),
"write_capacity": d.Get("write_capacity"),
}),
KeySchema: expandDynamoDbKeySchema(keySchemaMap),
TableName: aws.String(d.Get("name").(string)),
BillingMode: aws.String(d.Get("billing_mode").(string)),
KeySchema: expandDynamoDbKeySchema(keySchemaMap),
}

if d.Get("billing_mode").(string) == dynamodb.BillingModeProvisioned {
v_read, ok_read := d.GetOk("read_capacity")
v_write, ok_write := d.GetOk("write_capacity")
if !ok_read || !ok_write {
return fmt.Errorf("Read and Write capacity should be set when billing mode is PROVISIONED")
}

req.ProvisionedThroughput = expandDynamoDbProvisionedThroughput(map[string]interface{}{
"read_capacity": v_read,
"write_capacity": v_write,
})
}

if v, ok := d.GetOk("attribute"); ok {
Expand Down Expand Up @@ -360,10 +379,35 @@ func resourceAwsDynamoDbTableCreate(d *schema.ResourceData, meta interface{}) er

func resourceAwsDynamoDbTableUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).dynamodbconn
if d.HasChange("billing_mode") && !d.IsNewResource() {
req := &dynamodb.UpdateTableInput{
TableName: aws.String(d.Id()),
BillingMode: aws.String(d.Get("billing_mode").(string)),
}
if d.Get("billing_mode").(string) == dynamodb.BillingModeProvisioned {

v_read, ok_read := d.GetOk("read_capacity")
v_write, ok_write := d.GetOk("write_capacity")
if !ok_read || !ok_write {
return fmt.Errorf("Read and Write capacity should be set when billing mode is PROVISIONED")
}

req.ProvisionedThroughput = expandDynamoDbProvisionedThroughput(map[string]interface{}{
"read_capacity": v_read,
"write_capacity": v_write,
})
}
_, err := conn.UpdateTable(req)
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return fmt.Errorf("Error updating DynamoDB Table (%s) billing mode: %s", d.Id(), err)
}
if err := waitForDynamoDbTableToBeActive(d.Id(), d.Timeout(schema.TimeoutUpdate), conn); err != nil {
return fmt.Errorf("Error waiting for DynamoDB Table update: %s", err)
}
}
// Cannot create or delete index while updating table IOPS
// so we update IOPS separately
if (d.HasChange("read_capacity") || d.HasChange("write_capacity")) && !d.IsNewResource() {
if !d.HasChange("billing_mode") && d.Get("billing_mode").(string) == dynamodb.BillingModeProvisioned && (d.HasChange("read_capacity") || d.HasChange("write_capacity")) && !d.IsNewResource() {
_, err := conn.UpdateTable(&dynamodb.UpdateTableInput{
TableName: aws.String(d.Id()),
ProvisionedThroughput: expandDynamoDbProvisionedThroughput(map[string]interface{}{
Expand Down
76 changes: 76 additions & 0 deletions aws/resource_aws_dynamodb_table_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,33 @@ func TestAccAWSDynamoDbTable_enablePitr(t *testing.T) {
})
}

func TestAccAWSDynamoDbTable_BillingMode(t *testing.T) {
var conf dynamodb.DescribeTableOutput

rName := acctest.RandomWithPrefix("TerraformTestTable-")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSDynamoDbTableDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSDynamoDbConfigInitialState(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckInitialAWSDynamoDbTableExists("aws_dynamodb_table.basic-dynamodb-table", &conf),
testAccCheckInitialAWSDynamoDbTableConf("aws_dynamodb_table.basic-dynamodb-table"),
),
},
{
Config: testAccAWSDynamoDbBilling_PayPerRequest(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckDynamoDbTableHasBilling_PayPerRequest("aws_dynamodb_table.basic-dynamodb-table"),
),
},
},
})
}

func TestAccAWSDynamoDbTable_streamSpecification(t *testing.T) {
var conf dynamodb.DescribeTableOutput

Expand Down Expand Up @@ -989,6 +1016,10 @@ func testAccCheckInitialAWSDynamoDbTableConf(n string) resource.TestCheckFunc {

log.Printf("[DEBUG] Checking on table %s", rs.Primary.ID)

if *table.BillingModeSummary.BillingMode != dynamodb.BillingModeProvisioned {
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("Billing Mode was %s, not %s!", *table.BillingModeSummary.BillingMode, dynamodb.BillingModeProvisioned)
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
}

if *table.ProvisionedThroughput.WriteCapacityUnits != 2 {
return fmt.Errorf("Provisioned write capacity was %d, not 2!", table.ProvisionedThroughput.WriteCapacityUnits)
}
Expand Down Expand Up @@ -1066,6 +1097,36 @@ func testAccCheckDynamoDbTableHasPointInTimeRecoveryEnabled(n string) resource.T
}
}

func testAccCheckDynamoDbTableHasBilling_PayPerRequest(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No DynamoDB table name specified!")
}

conn := testAccProvider.Meta().(*AWSClient).dynamodbconn
params := &dynamodb.DescribeTableInput{
TableName: aws.String(rs.Primary.ID),
}
resp, err := conn.DescribeTable(params)

if err != nil {
return err
}
table := resp.Table

if *table.BillingModeSummary.BillingMode != dynamodb.BillingModePayPerRequest {
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("Billing Mode was %s, not %s!", *table.BillingModeSummary.BillingMode, dynamodb.BillingModePayPerRequest)
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
}

return nil
}
}

func testAccCheckDynamoDbTableWasUpdated(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
Expand Down Expand Up @@ -1186,6 +1247,21 @@ resource "aws_dynamodb_table" "basic-dynamodb-table" {
`, rName)
}

func testAccAWSDynamoDbBilling_PayPerRequest(rName string) string {
return fmt.Sprintf(`
resource "aws_dynamodb_table" "basic-dynamodb-table" {
name = "%s"
billing_mode = "PAY_PER_REQUEST"
hash_key = "TestTableHashKey"

attribute {
name = "TestTableHashKey"
type = "S"
}
}
`, rName)
}

func testAccAWSDynamoDbConfigInitialState(rName string) string {
return fmt.Sprintf(`
resource "aws_dynamodb_table" "basic-dynamodb-table" {
Expand Down
6 changes: 4 additions & 2 deletions website/docs/r/dynamodb_table.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ in the [AWS SDK example documentation](https://docs.aws.amazon.com/amazondynamod
```hcl
resource "aws_dynamodb_table" "basic-dynamodb-table" {
name = "GameScores"
billing_mode = "PROVISIONED"
read_capacity = 20
write_capacity = 20
hash_key = "UserId"
Expand Down Expand Up @@ -83,10 +84,11 @@ The following arguments are supported:

* `name` - (Required) The name of the table, this needs to be unique
within a region.
* `billing_mode` - (Optional) Controls how you are charged for read and write throughput and how you manage capacity. The valid values are `PROVISIONED` and `PAY_PER_REQUEST`. Defaults to `PROVISIONED`.
* `hash_key` - (Required, Forces new resource) The attribute to use as the hash (partition) key. Must also be defined as an `attribute`, see below.
* `range_key` - (Optional, Forces new resource) The attribute to use as the range (sort) key. Must also be defined as an `attribute`, see below.
* `write_capacity` - (Required) The number of write units for this table
* `read_capacity` - (Required) The number of read units for this table
* `write_capacity` - (Optional) The number of write units for this table. If the `billing_mode` is `PROVISIONED`, this field is required.
sunilkumarmohanty marked this conversation as resolved.
Show resolved Hide resolved
* `read_capacity` - (Optional) The number of read units for this table. If the `billing_mode` is `PROVISIONED`, this field is required.
* `attribute` - (Required) List of nested attribute definitions. Only required for `hash_key` and `range_key` attributes. Each attribute has two properties:
* `name` - (Required) The name of the attribute
* `type` - (Required) Attribute type, which must be a scalar type: `S`, `N`, or `B` for (S)tring, (N)umber or (B)inary data
Expand Down