Skip to content

Commit

Permalink
Merge branch 'dynamodb_table_item_attribute' into coveo-master
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien Duchesne committed Oct 1, 2018
2 parents 42a2ab1 + 3cb6a0b commit e337493
Show file tree
Hide file tree
Showing 23 changed files with 3,198 additions and 928 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
## 1.39.0 (Unreleased)
## 1.38.0 (September 26, 2018)

FEATURES:
Expand All @@ -12,7 +13,7 @@ ENHANCEMENTS:
* resource/aws_codebuild_project: Add `arn` attribute ([#5973](https://github.com/terraform-providers/terraform-provider-aws/issues/5973))
* resource/aws_launch_template: Support `credit_specification` configuration of T3 instance types ([#5922](https://github.com/terraform-providers/terraform-provider-aws/issues/5922))
* resource/aws_launch_template: Allow `network_interface` `ipv6_address_count` configuration ([#5771](https://github.com/terraform-providers/terraform-provider-aws/issues/5771))
* resource/aws_rds_cluster: Support `parallelquery` `engine_mode` argument [GH=5980]
* resource/aws_rds_cluster: Support `parallelquery` `engine_mode` argument ([#5980](https://github.com/terraform-providers/terraform-provider-aws/issues/5980))

BUG FIXES:

Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ func Provider() terraform.ResourceProvider {
"aws_dx_public_virtual_interface": resourceAwsDxPublicVirtualInterface(),
"aws_dynamodb_table": resourceAwsDynamoDbTable(),
"aws_dynamodb_table_item": resourceAwsDynamoDbTableItem(),
"aws_dynamodb_table_item_attribute": resourceAwsDynamoDbTableItemAttribute(),
"aws_dynamodb_global_table": resourceAwsDynamoDbGlobalTable(),
"aws_ebs_snapshot": resourceAwsEbsSnapshot(),
"aws_ebs_volume": resourceAwsEbsVolume(),
Expand Down
190 changes: 190 additions & 0 deletions aws/resource_aws_dynamodb_table_item_attribute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package aws

import (
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/hashicorp/terraform/helper/schema"
)

const (
updateExpressionSet = "SET"
updateExpressionRemove = "REMOVE"
)

func resourceAwsDynamoDbTableItemAttribute() *schema.Resource {
return &schema.Resource{
Create: resourceAwsDynamoDbTableItemAttributeUpdate,
Read: resourceAwsDynamoDbTableItemAttributeRead,
Update: resourceAwsDynamoDbTableItemAttributeUpdate,
Delete: resourceAwsDynamoDbTableItemAttributeDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"table_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"hash_key_value": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"range_key_value": {
Type: schema.TypeString,
ForceNew: true,
Optional: true,
},
"attribute_key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"attribute_value": {
Type: schema.TypeString,
Required: true,
},
},
}
}

func resourceAwsDynamoDbTableItemAttributeDelete(d *schema.ResourceData, meta interface{}) error {
return resourceAwsDynamoDbTableItemAttributeModify(updateExpressionRemove, d, meta)
}

func resourceAwsDynamoDbTableItemAttributeUpdate(d *schema.ResourceData, meta interface{}) error {
if err := resourceAwsDynamoDbTableItemAttributeModify(updateExpressionSet, d, meta); err != nil {
return err
}
return resourceAwsDynamoDbTableItemAttributeRead(d, meta)
}

func resourceAwsDynamoDbTableItemAttributeModify(action string, d *schema.ResourceData, meta interface{}) error {
log.Printf("[DEBUG] %s DynamoDB table %s", action, d.Id())
conn := meta.(*AWSClient).dynamodbconn

tableName := d.Get("table_name").(string)

hashKeyValue := d.Get("hash_key_value").(string)
rangeKeyValue := d.Get("range_key_value").(string)
attributeKey := d.Get("attribute_key").(string)
attributeValue := d.Get("attribute_value").(string)

hashKeyName, rangeKeyName, err := resourceAwsDynamoDbTableItemAttributeGetKeysInfo(conn, tableName)
if err != nil {
return err
}

updateItemInput := &dynamodb.UpdateItemInput{
Key: resourceAwsDynamoDbTableItemAttributeGetQueryKey(hashKeyName, hashKeyValue, rangeKeyName, rangeKeyValue),
TableName: aws.String(tableName),
}

if d.IsNewResource() {
updateItemInput.ConditionExpression = aws.String("attribute_not_exists(#key)")
}

updateItemInput.ExpressionAttributeNames = map[string]*string{
"#key": aws.String(attributeKey),
}
if action == updateExpressionSet {
updateItemInput.UpdateExpression = aws.String(fmt.Sprintf("%s #key = :v", updateExpressionSet))
updateItemInput.ExpressionAttributeValues = map[string]*dynamodb.AttributeValue{
":v": {
S: aws.String(attributeValue),
},
}
} else if action == updateExpressionRemove {
updateItemInput.UpdateExpression = aws.String(fmt.Sprintf("%s #key", updateExpressionRemove))
}

if _, err := conn.UpdateItem(updateItemInput); err != nil {
return err
}

id := fmt.Sprintf("%s:%s:%s:%s", tableName, hashKeyValue, rangeKeyValue, attributeKey)
d.SetId(id)

return nil
}

func resourceAwsDynamoDbTableItemAttributeRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).dynamodbconn

log.Printf("[DEBUG] Loading data for DynamoDB table item attribute '%s'", d.Id())

idParts := strings.Split(d.Id(), ":")
tableName, hashKeyValue, rangeKeyValue, attributeKey := idParts[0], idParts[1], idParts[2], idParts[3]

hashKeyName, rangeKeyName, err := resourceAwsDynamoDbTableItemAttributeGetKeysInfo(conn, tableName)
if err != nil {
return err
}

result, err := conn.GetItem(&dynamodb.GetItemInput{
ConsistentRead: aws.Bool(true),
ExpressionAttributeNames: map[string]*string{
"#key": aws.String(attributeKey),
},
Key: resourceAwsDynamoDbTableItemAttributeGetQueryKey(hashKeyName, hashKeyValue, rangeKeyName, rangeKeyValue),
TableName: aws.String(tableName),
ProjectionExpression: aws.String("#key"),
})
if err != nil {
if isAWSErr(err, dynamodb.ErrCodeResourceNotFoundException, "") {
log.Printf("[WARN] Dynamodb Table Item (%s) not found, error code (404)", d.Id())
d.SetId("")
return nil
}

return fmt.Errorf("Error retrieving DynamoDB table item: %s", err)
}

if result.Item == nil {
log.Printf("[WARN] Dynamodb Table Item (%s) not found", d.Id())
d.SetId("")
return nil
}
d.Set("table_name", tableName)
d.Set("hash_key_value", hashKeyValue)
d.Set("range_key_value", rangeKeyValue)
d.Set("attribute_key", attributeKey)
d.Set("attribute_value", result.Item[attributeKey].S)

return nil
}

func resourceAwsDynamoDbTableItemAttributeGetKeysInfo(conn *dynamodb.DynamoDB, tableName string) (string, string, error) {
var hashKeyName, rangeKeyName string
if out, err := conn.DescribeTable(&dynamodb.DescribeTableInput{
TableName: aws.String(tableName),
}); err == nil {
for _, key := range out.Table.KeySchema {
if *key.KeyType == dynamodb.KeyTypeHash {
hashKeyName = *key.AttributeName
} else if *key.KeyType == dynamodb.KeyTypeRange {
rangeKeyName = *key.AttributeName
}
}
} else {
return "", "", fmt.Errorf("Error describing table %s: %v", tableName, err)
}

return hashKeyName, rangeKeyName, nil
}

func resourceAwsDynamoDbTableItemAttributeGetQueryKey(hashKeyName string, hashKeyValue string, rangeKeyName string, rangeKeyValue string) map[string]*dynamodb.AttributeValue {
queryKey := map[string]*dynamodb.AttributeValue{
hashKeyName: {S: aws.String(hashKeyValue)},
}
if rangeKeyValue != "" {
queryKey[rangeKeyName] = &dynamodb.AttributeValue{S: aws.String(rangeKeyValue)}
}
return queryKey
}
Loading

0 comments on commit e337493

Please sign in to comment.