forked from cloudposse/terraform-null-label
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.tf
146 lines (124 loc) · 7.19 KB
/
main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
locals {
defaults = {
label_order = ["namespace", "environment", "stage", "name", "attributes"]
regex_replace_chars = "/[^-a-zA-Z0-9]/"
delimiter = "-"
replacement = ""
id_length_limit = 0
id_hash_length = 5
label_key_case = "title"
label_value_case = "lower"
}
# So far, we have decided not to allow overriding replacement or id_hash_length
replacement = local.defaults.replacement
id_hash_length = local.defaults.id_hash_length
# The values provided by variables supersede the values inherited from the context object,
# except for tags and attributes which are merged.
input = {
# It would be nice to use coalesce here, but we cannot, because it
# is an error for all the arguments to coalesce to be empty.
enabled = var.enabled == null ? var.context.enabled : var.enabled
namespace = var.namespace == null ? var.context.namespace : var.namespace
environment = var.environment == null ? var.context.environment : var.environment
stage = var.stage == null ? var.context.stage : var.stage
name = var.name == null ? var.context.name : var.name
delimiter = var.delimiter == null ? var.context.delimiter : var.delimiter
# modules tack on attributes (passed by var) to the end of the list (passed by context)
attributes = compact(distinct(concat(coalesce(var.context.attributes, []), coalesce(var.attributes, []))))
tags = merge(var.context.tags, var.tags)
additional_tag_map = merge(var.context.additional_tag_map, var.additional_tag_map)
label_order = var.label_order == null ? var.context.label_order : var.label_order
regex_replace_chars = var.regex_replace_chars == null ? var.context.regex_replace_chars : var.regex_replace_chars
id_length_limit = var.id_length_limit == null ? var.context.id_length_limit : var.id_length_limit
label_key_case = var.label_key_case == null ? lookup(var.context, "label_key_case", null) : var.label_key_case
label_value_case = var.label_value_case == null ? lookup(var.context, "label_value_case", null) : var.label_value_case
}
enabled = local.input.enabled
regex_replace_chars = coalesce(local.input.regex_replace_chars, local.defaults.regex_replace_chars)
# string_label_names are names of inputs that are strings (not list of strings) used as labels
string_label_names = ["name", "namespace", "environment", "stage"]
normalized_labels = { for k in local.string_label_names : k =>
local.input[k] == null ? "" : replace(local.input[k], local.regex_replace_chars, local.replacement)
}
normalized_attributes = compact(distinct([for v in local.input.attributes : replace(v, local.regex_replace_chars, local.replacement)]))
formatted_labels = { for k in local.string_label_names : k => local.label_value_case == "none" ? local.normalized_labels[k] :
local.label_value_case == "title" ? title(lower(local.normalized_labels[k])) :
local.label_value_case == "upper" ? upper(local.normalized_labels[k]) : lower(local.normalized_labels[k])
}
attributes = compact(distinct([
for v in local.normalized_attributes : (local.label_value_case == "none" ? v :
local.label_value_case == "title" ? title(lower(v)) :
local.label_value_case == "upper" ? upper(v) : lower(v))
]))
name = local.formatted_labels["name"]
namespace = local.formatted_labels["namespace"]
environment = local.formatted_labels["environment"]
stage = local.formatted_labels["stage"]
delimiter = local.input.delimiter == null ? local.defaults.delimiter : local.input.delimiter
label_order = local.input.label_order == null ? local.defaults.label_order : coalescelist(local.input.label_order, local.defaults.label_order)
id_length_limit = local.input.id_length_limit == null ? local.defaults.id_length_limit : local.input.id_length_limit
label_key_case = local.input.label_key_case == null ? local.defaults.label_key_case : local.input.label_key_case
label_value_case = local.input.label_value_case == null ? local.defaults.label_value_case : local.input.label_value_case
additional_tag_map = merge(var.context.additional_tag_map, var.additional_tag_map)
tags = merge(local.generated_tags, local.input.tags)
tags_as_list_of_maps = flatten([
for key in keys(local.tags) : merge(
{
key = key
value = local.tags[key]
}, var.additional_tag_map)
])
tags_context = {
# For AWS we need `Name` to be disambiguated since it has a special meaning
name = local.id
namespace = local.namespace
environment = local.environment
stage = local.stage
attributes = local.id_context.attributes
}
generated_tags = {
for l in keys(local.tags_context) :
local.label_key_case == "upper" ? upper(l) : (
local.label_key_case == "lower" ? lower(l) : title(lower(l))
) => local.tags_context[l] if length(local.tags_context[l]) > 0
}
id_context = {
name = local.name
namespace = local.namespace
environment = local.environment
stage = local.stage
attributes = join(local.delimiter, local.attributes)
}
labels = [for l in local.label_order : local.id_context[l] if length(local.id_context[l]) > 0]
id_full = join(local.delimiter, local.labels)
# Create a truncated ID if needed
delimiter_length = length(local.delimiter)
# Calculate length of normal part of ID, leaving room for delimiter and hash
id_truncated_length_limit = local.id_length_limit - (local.id_hash_length + local.delimiter_length)
# Truncate the ID and ensure a single (not double) trailing delimiter
id_truncated = local.id_truncated_length_limit <= 0 ? "" : "${trimsuffix(substr(local.id_full, 0, local.id_truncated_length_limit), local.delimiter)}${local.delimiter}"
# Support usages that disallow numeric characters. Would prefer tr 0-9 q-z but Terraform does not support it.
id_hash_plus = "${md5(local.id_full)}qrstuvwxyz"
id_hash_case = local.label_value_case == "title" ? title(local.id_hash_plus) : local.label_value_case == "upper" ? upper(local.id_hash_plus) : local.label_value_case == "lower" ? lower(local.id_hash_plus) : local.id_hash_plus
id_hash = replace(local.id_hash_case, local.regex_replace_chars, local.replacement)
# Create the short ID by adding a hash to the end of the truncated ID
id_short = substr("${local.id_truncated}${local.id_hash}", 0, local.id_length_limit)
id = local.id_length_limit != 0 && length(local.id_full) > local.id_length_limit ? local.id_short : local.id_full
# Context of this label to pass to other label modules
output_context = {
enabled = local.enabled
name = local.name
namespace = local.namespace
environment = local.environment
stage = local.stage
delimiter = local.delimiter
attributes = local.attributes
tags = local.tags
additional_tag_map = local.additional_tag_map
label_order = local.label_order
regex_replace_chars = local.regex_replace_chars
id_length_limit = local.id_length_limit
label_key_case = local.label_key_case
label_value_case = local.label_value_case
}
}