Skip to content

Commit 53ed39d

Browse files
author
kfc-manager
committed
enha: added option to define global secondary index keys
1 parent 43280ef commit 53ed39d

File tree

5 files changed

+287
-35
lines changed

5 files changed

+287
-35
lines changed

main.tf

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
11
################################
2-
# DynamoDB #
2+
# Table #
33
################################
44

5-
resource "aws_dynamodb_table" "main" {
6-
billing_mode = "PAY_PER_REQUEST"
7-
hash_key = try(var.partition_key["name"], null)
8-
range_key = try(var.sort_key["name"], null)
9-
name = var.identifier
10-
11-
attribute {
12-
name = try(var.partition_key["name"], null)
13-
type = try(var.partition_key["type"], null)
14-
}
5+
locals {
6+
key_attributes = var.sort_key != null ? [var.hash_key, var.sort_key] : [var.hash_key]
7+
gsi_hash_attributes = [for v in var.gsi_keys : v["hash_key"]]
8+
gsi_sort_attributes = [for v in var.gsi_keys : try(v["sort_key"], null) if try(v["sort_key"], null) != null]
9+
attributes = toset(concat(local.key_attributes, local.gsi_hash_attributes, local.gsi_sort_attributes))
10+
}
1511

16-
attribute {
17-
name = try(var.sort_key["name"], null)
18-
type = try(var.sort_key["type"], null)
19-
}
12+
resource "aws_dynamodb_table" "main" {
13+
billing_mode = var.provisioned != null ? "PROVISIONED" : "PAY_PER_REQUEST"
14+
hash_key = var.hash_key["name"]
15+
range_key = try(var.sort_key["name"], null)
16+
name = var.identifier
17+
read_capacity = try(var.provisioned["read_capacity"], null)
18+
write_capacity = try(var.provisioned["write_capacity"], null)
2019

2120
dynamic "attribute" {
22-
for_each = var.attributes
21+
for_each = local.attributes
22+
content {
23+
name = attribute.value["name"]
24+
type = attribute.value["type"]
25+
}
26+
}
2327

28+
dynamic "global_secondary_index" {
29+
for_each = var.gsi_keys
2430
content {
25-
name = try(attribute.value["name"], null)
26-
type = try(attribute.value["type"], null)
31+
name = global_secondary_index.value["name"] != null ? global_secondary_index.value["name"] : global_secondary_index.value["hash_key"]["name"]
32+
hash_key = global_secondary_index.value["hash_key"]["name"]
33+
range_key = try(global_secondary_index.value["sort_key"]["name"], null)
34+
projection_type = try(global_secondary_index.value["projection_type"], null)
35+
non_key_attributes = try(global_secondary_index.value["non_key_attributes"], null)
36+
read_capacity = try(global_secondary_index.value["read_capacity"], null)
37+
write_capacity = try(global_secondary_index.value["write_capacity"], null)
2738
}
2839
}
2940

outputs.tf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
output "name" {
2+
description = "Name of the DynamoDB table."
3+
value = try(aws_dynamodb_table.main.id, null)
4+
}
5+
16
output "arn" {
27
description = "ARN of the DynamoDB table."
38
value = try(aws_dynamodb_table.main.arn, null)

tests/attributes.tftest.hcl

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
provider "aws" {
2+
region = "eu-central-1"
3+
default_tags {
4+
tags = {
5+
Environment = "Test"
6+
}
7+
}
8+
}
9+
10+
run "hash_key" {
11+
command = plan
12+
13+
variables {
14+
identifier = "abc"
15+
hash_key = {
16+
name = "TestPKey"
17+
type = "S"
18+
}
19+
}
20+
21+
assert {
22+
condition = length(local.attributes) == 1
23+
error_message = "Unexpected amount of attributes were created"
24+
}
25+
}
26+
27+
run "hash_and_sort_key" {
28+
command = plan
29+
30+
variables {
31+
identifier = "abc"
32+
hash_key = {
33+
name = "TestPKey"
34+
type = "S"
35+
}
36+
sort_key = {
37+
name = "TestSKey"
38+
type = "S"
39+
}
40+
}
41+
42+
assert {
43+
condition = length(local.attributes) == 2
44+
error_message = "Unexpected amount of attributes were created"
45+
}
46+
}
47+
48+
run "single_gsi_hash_key" {
49+
command = plan
50+
51+
variables {
52+
identifier = "abc"
53+
hash_key = {
54+
name = "TestPKey"
55+
type = "S"
56+
}
57+
gsi_keys = [{
58+
hash_key = {
59+
name = "GSIPKey"
60+
type = "S"
61+
}
62+
}]
63+
}
64+
65+
assert {
66+
condition = length(local.attributes) == 2
67+
error_message = "Unexpected amount of attributes were created"
68+
}
69+
}
70+
71+
run "single_gsi_hash_and_sort_key" {
72+
command = plan
73+
74+
variables {
75+
identifier = "abc"
76+
hash_key = {
77+
name = "TestPKey"
78+
type = "S"
79+
}
80+
gsi_keys = [{
81+
hash_key = {
82+
name = "GSIPKey"
83+
type = "S"
84+
}
85+
sort_key = {
86+
name = "GSISKey"
87+
type = "S"
88+
}
89+
}]
90+
}
91+
92+
assert {
93+
condition = length(local.attributes) == 3
94+
error_message = "Unexpected amount of attributes were created"
95+
}
96+
}
97+
98+
run "duplicate_gsi_sort_key" {
99+
command = plan
100+
101+
variables {
102+
identifier = "abc"
103+
hash_key = {
104+
name = "TestPKey"
105+
type = "S"
106+
}
107+
gsi_keys = [{
108+
hash_key = {
109+
name = "GSIPKey"
110+
type = "S"
111+
}
112+
sort_key = {
113+
name = "TestPKey"
114+
type = "S"
115+
}
116+
}]
117+
}
118+
119+
assert {
120+
condition = length(local.attributes) == 2
121+
error_message = "Unexpected amount of attributes were created"
122+
}
123+
}
124+
125+
run "multiple_gsi_keys" {
126+
command = plan
127+
128+
variables {
129+
identifier = "abc"
130+
hash_key = {
131+
name = "TestPKey"
132+
type = "S"
133+
}
134+
gsi_keys = [{
135+
hash_key = {
136+
name = "1GSIPKey"
137+
type = "S"
138+
}
139+
sort_key = {
140+
name = "1GSISKey"
141+
type = "S"
142+
}
143+
},
144+
{
145+
hash_key = {
146+
name = "2GSIPKey"
147+
type = "S"
148+
}
149+
sort_key = {
150+
name = "2GSISKey"
151+
type = "S"
152+
}
153+
},
154+
{
155+
hash_key = {
156+
name = "3GSIPKey"
157+
type = "S"
158+
}
159+
sort_key = {
160+
name = "3GSISKey"
161+
type = "S"
162+
}
163+
}]
164+
}
165+
166+
assert {
167+
condition = length(local.attributes) == 7
168+
error_message = "Unexpected amount of attributes were created"
169+
}
170+
}
171+
172+
run "multiple_duplicate_gsi_keys" {
173+
command = plan
174+
175+
variables {
176+
identifier = "abc"
177+
hash_key = {
178+
name = "TestPKey"
179+
type = "S"
180+
}
181+
sort_key = {
182+
name = "TestSKey"
183+
type = "S"
184+
}
185+
gsi_keys = [{
186+
hash_key = {
187+
name = "1GSIPKey"
188+
type = "S"
189+
}
190+
sort_key = {
191+
name = "TestPKey"
192+
type = "S"
193+
}
194+
},
195+
{
196+
hash_key = {
197+
name = "TestSKey"
198+
type = "S"
199+
}
200+
sort_key = {
201+
name = "2GSISKey"
202+
type = "S"
203+
}
204+
},
205+
{
206+
hash_key = {
207+
name = "1GSIPKey"
208+
type = "S"
209+
}
210+
sort_key = {
211+
name = "2GSISKey"
212+
type = "S"
213+
}
214+
}]
215+
}
216+
217+
assert {
218+
condition = length(local.attributes) == 4
219+
error_message = "Unexpected amount of attributes were created"
220+
}
221+
}

tests/table.tftest.hcl

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,10 @@ run "invalid_identifier" {
1212

1313
variables {
1414
identifier = "a"
15-
partition_key = {
15+
hash_key = {
1616
name = "TestPKey"
1717
type = "S"
1818
}
19-
sort_key = {
20-
name = "TestSKey"
21-
type = "S"
22-
}
2319
}
2420

2521
expect_failures = [var.identifier]
@@ -30,13 +26,11 @@ run "valid_identifier" {
3026

3127
variables {
3228
identifier = "abc"
33-
partition_key = {
29+
hash_key = {
3430
name = "TestPKey"
3531
type = "S"
3632
}
37-
sort_key = {
38-
name = "TestSKey"
39-
type = "S"
40-
}
4133
}
4234
}
35+
36+

variables.tf

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,48 @@ variable "identifier" {
77
}
88
}
99

10-
variable "partition_key" {
11-
description = "Partition key of the table."
10+
variable "hash_key" {
11+
description = "Partition or hash key of the table."
1212
type = object({
1313
name = string
1414
type = string
1515
})
1616
}
1717

1818
variable "sort_key" {
19-
description = "Sort key of the table."
19+
description = "Sort or range key of the table."
2020
type = object({
2121
name = string
2222
type = string
2323
})
24+
default = null
2425
}
2526

26-
variable "attributes" {
27-
description = "List of attributes of the table."
27+
variable "provisioned" {
28+
description = "Objetct to define read and write capacity for a provisioned table. If not defined an on demand table will be created."
29+
type = object({
30+
read_capacity = number
31+
write_capacity = number
32+
})
33+
default = null
34+
}
35+
36+
variable "gsi_keys" {
37+
description = "Global secondary index keys of the table."
2838
type = list(object({
29-
name = string
30-
type = string
39+
name = optional(string, null)
40+
hash_key = object({
41+
name = string
42+
type = string
43+
})
44+
sort_key = optional(object({
45+
name = string
46+
type = string
47+
}), null)
48+
projection_type = optional(string, "ALL")
49+
non_key_attributes = optional(list(string), null)
50+
read_capacity = optional(number, null)
51+
write_capacity = optional(number, null)
3152
}))
3253
default = []
3354
}

0 commit comments

Comments
 (0)