Skip to content

Commit

Permalink
added dynamodb table module
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel Bakhmetev committed Sep 11, 2024
1 parent 7128d90 commit 1fb213b
Show file tree
Hide file tree
Showing 8 changed files with 362 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module "example" {
| Label | [tf-label](https://github.com/Devoteam/terraform-modules/tree/main/tf-label) | Terraform module for consistent names and tags generation for resources. |
| AWS Lambda | [tf-aws-lambda](https://github.com/Devoteam/terraform-modules/tree/main/tf-aws-lambda) | Terraform module for launching Lambda Functions |
| AWS Lambda Layer | [tf-aws-lambda-layer](https://github.com/Devoteam/terraform-modules/tree/main/tf-aws-lambda-layer) | Terraform module for Lambda Functions Layer definition |
| AWS DynamoDb | [tf-aws-dynamodb](https://github.com/Devoteam/terraform-modules/tree/main/tf-dynamodb) | Terraform module for DynamoDb table definition |

## Contributing

Expand Down
58 changes: 58 additions & 0 deletions tf-aws-dynamodb/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Terraform module tf-aws-dynamodb

## Terraform module for creating DynamoDb resources.

## Usage

```
module "dynamodb_table" {
source = "git::https://github.com/devoteam/terraform-modules.git//tf-aws-dynamodb"
namespace = "devoteam"
environment = "prod"
project = "genai"
component = "db"
name = "logs_table"
hash_key = "HashKey"
range_key = "RangeKey"
dynamodb_attributes = [
{
name = "Component"
type = "S"
},
{
name = "Timestamp"
type = "S"
}
]
local_secondary_index_map = [
{
name = "TimestampSortIndex"
range_key = "Timestamp"
projection_type = "INCLUDE"
non_key_attributes = ["HashKey", "RangeKey"]
},
{
name = "ComponentIndex"
range_key = "Timestamp"
projection_type = "INCLUDE"
non_key_attributes = ["HashKey", "RangeKey"]
}
]
global_secondary_index_map = [
{
name = "ComponentGlobalIndex"
hash_key = "Component"
range_key = "Timestamp"
write_capacity = 5
read_capacity = 5
projection_type = "INCLUDE"
non_key_attributes = ["HashKey", "RangeKey"]
}
]
}
```
97 changes: 97 additions & 0 deletions tf-aws-dynamodb/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Description: This module creates an AWS DynamoDB table.
terraform {
required_version = ">= 0.13.0"
}

locals {
fully_qualified_name = "${module.name.id}-${var.table_name}"
attributes = concat(
[
{
name = var.hash_key
type = var.hash_key_type
}
],
var.dynamodb_attributes
)
attributes_final = length(var.range_key) == 0 ? attributes : concat(
[
{
name = var.range_key
type = var.range_key_type
}
],
attributes
)
}

module "name" {
source = "../tf-label"
namespace = var.namespace
environment = var.environment
project = var.project
component = var.component
label_case = var.label_case
}

resource "aws_dynamodb_table" "default" {
name = local.fully_qualified_name
billing_mode = var.billing_mode
read_capacity = var.billing_mode == "PAY_PER_REQUEST" ? null : var.read_capacity
write_capacity = var.billing_mode == "PAY_PER_REQUEST" ? null : var.write_capacity
hash_key = var.hash_key
range_key = var.range_key
stream_enabled = var.enable_streams
stream_view_type = var.enable_streams ? var.stream_view_type : ""
table_class = var.table_class

lifecycle {
ignore_changes = [
read_capacity,
write_capacity
]
}

server_side_encryption {
enabled = var.enable_encryption
kms_key_arn = var.server_side_encryption_kms_key_arn
}

dynamic "attribute" {
for_each = local.attributes_final
content {
name = attribute.value.name
type = attribute.value.type
}
}

dynamic "global_secondary_index" {
for_each = var.global_secondary_index_map
content {
hash_key = global_secondary_index.value.hash_key
name = global_secondary_index.value.name
non_key_attributes = lookup(global_secondary_index.value, "non_key_attributes", null)
projection_type = global_secondary_index.value.projection_type
range_key = lookup(global_secondary_index.value, "range_key", null)
read_capacity = lookup(global_secondary_index.value, "read_capacity", null)
write_capacity = lookup(global_secondary_index.value, "write_capacity", null)
}
}

dynamic "local_secondary_index" {
for_each = var.local_secondary_index_map
content {
name = local_secondary_index.value.name
non_key_attributes = lookup(local_secondary_index.value, "non_key_attributes", null)
projection_type = local_secondary_index.value.projection_type
range_key = local_secondary_index.value.range_key
}
}

ttl {
enabled = var.ttl_attribute != "" ? var.ttl_enabled : false
attribute_name = var.ttl_attribute
}

tags = module.name.tags
}
34 changes: 34 additions & 0 deletions tf-aws-dynamodb/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
output "table_name" {
value = join("", aws_dynamodb_table.default[*].name)
description = "DynamoDB table name"
}

output "table_id" {
value = join("", aws_dynamodb_table.default[*].id)
description = "DynamoDB table ID"
}

output "table_arn" {
value = join("", aws_dynamodb_table.default[*].arn)
description = "DynamoDB table ARN"
}

output "global_secondary_index_names" {
value = null_resource.global_secondary_index_names[*].triggers.name
description = "DynamoDB secondary index names"
}

output "local_secondary_index_names" {
value = null_resource.local_secondary_index_names[*].triggers.name
description = "DynamoDB local index names"
}

output "table_stream_arn" {
value = join("", aws_dynamodb_table.default[*].stream_arn)
description = "DynamoDB table stream ARN"
}

output "table_stream_label" {
value = join("", aws_dynamodb_table.default[*].stream_label)
description = "DynamoDB table stream label"
}
164 changes: 164 additions & 0 deletions tf-aws-dynamodb/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
variable "namespace" {
type = string
default = null
description = "The organization name, e.g. 'devoteam'"
}

variable "environment" {
type = string
default = null
description = "The stage name 'prod', 'staging', 'dev', 'test'"
}

variable "project" {
type = string
default = null
description = "The project name, e.g. 'genai'."
}

variable "component" {
type = string
default = null
description = "The component name, e.g. 'api'."
}

variable "delimiter" {
type = string
default = null
description = "Delimiter between ID elements."
}

variable "label_case" {
type = string
default = null
description = "Letter case of label elements"

validation {
condition = var.label_case == null ? true : contains(["lower", "upper"], var.label_case)
error_message = "Allowed values: `lower`, `upper`."
}
}

variable "table_name" {
type = string
default = null
description = "Table name. If provided, the dynamodb table will be created with this name instead of generating the name from the variables"
}

variable "billing_mode" {
type = string
default = "PAY_PER_REQUEST"
description = "DynamoDB Billing mode. Can be PROVISIONED or PAY_PER_REQUEST"
}

variable "read_capacity" {
type = number
default = 5
description = "Number of read units for this table. If the billing_mode is PROVISIONED, this field is required."
}

variable "write_capacity" {
type = number
default = 5
description = "Number of write units for this table. If the billing_mode is PROVISIONED, this field is required."
}

variable "enable_streams" {
type = bool
default = false
description = "Enable DynamoDB streams"
}

variable "stream_view_type" {
type = string
default = ""
description = "Valid values are KEYS_ONLY, NEW_IMAGE, OLD_IMAGE, NEW_AND_OLD_IMAGES."
}

variable "enable_encryption" {
type = bool
default = true
description = "Enable DynamoDB server-side encryption"
}

variable "server_side_encryption_kms_key_arn" {
type = string
default = null
description = "The ARN of the CMK that should be used for the AWS KMS encryption. This attribute should only be specified if the key is different from the default DynamoDB CMK, alias/aws/dynamodb."
}

variable "hash_key" {
type = string
description = "DynamoDB table Hash Key"
}

variable "hash_key_type" {
type = string
default = "S"
description = "Hash Key type, which must be a scalar type: `S`, `N`, or `B` for (S)tring, (N)umber or (B)inary data"
}

variable "range_key" {
type = string
default = ""
description = "DynamoDB table Range Key"
}

variable "range_key_type" {
type = string
default = "S"
description = "Range Key type, which must be a scalar type: `S`, `N`, or `B` for (S)tring, (N)umber or (B)inary data"
}

variable "ttl_attribute" {
type = string
default = "Expires"
description = "Name of the table attribute to store the TTL timestamp in. Required if enabled is true, must not be set otherwise."
}

variable "ttl_enabled" {
type = bool
default = false
description = "Whether TTL is enabled. Default value is false."
}

variable "dynamodb_attributes" {
type = list(object({
name = string
type = string
}))
default = []
description = "Additional DynamoDB attributes in the form of a list of mapped values"
}

variable "global_secondary_index_map" {
type = list(object({
hash_key = string
name = string
non_key_attributes = list(string)
projection_type = string
range_key = string
read_capacity = number
write_capacity = number
}))
default = []
description = "Additional global secondary indexes in the form of a list of mapped values"
}

variable "local_secondary_index_map" {
type = list(object({
name = string
non_key_attributes = list(string)
projection_type = string
range_key = string
}))
default = []
description = "Additional local secondary indexes in the form of a list of mapped values"
}

variable "table_class" {
type = string
default = "STANDARD"
description = "Storage class of the table. Valid values are STANDARD and STANDARD_INFREQUENT_ACCESS. Default value is STANDARD."
}

3 changes: 3 additions & 0 deletions tf-aws-lambda-layer/main.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Description: This module creates a Lambda Layer.
terraform {
required_version = ">= 0.13.0"
}

locals {
fully_qualified_name = "${module.name.id}-${var.layer_name}"
Expand Down
4 changes: 4 additions & 0 deletions tf-aws-lambda/main.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Description: This module creates an AWS Lambda function.
terraform {
required_version = ">= 0.13.0"
}

locals {
fully_qualified_name = "${module.name.id}-${var.function_name}"
partition = data.aws_partition.this[0].partition
Expand Down
3 changes: 1 addition & 2 deletions tf-label/main.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Description: This module is used to generate labels and tags for resources in Terraform.
terraform {
required_version = ">= 0.13.0"
}

locals {

defaults = {
delimiter = "-"
label_case = "lower"
Expand Down Expand Up @@ -52,5 +52,4 @@ locals {
tags = merge(local.generated_tags, local.input.tags)

id = join(local.delimiter, [local.namespace, local.project, local.component, local.environment])

}

0 comments on commit 1fb213b

Please sign in to comment.