-
-
Notifications
You must be signed in to change notification settings - Fork 540
/
terraform_docs.sh
executable file
·228 lines (186 loc) · 7.83 KB
/
terraform_docs.sh
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/usr/bin/env bash
set -eo pipefail
# globals variables
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
readonly SCRIPT_DIR
# shellcheck source=_common.sh
. "$SCRIPT_DIR/_common.sh"
insertion_marker_begin="<!-- BEGIN_TF_DOCS -->"
insertion_marker_end="<!-- END_TF_DOCS -->"
# Old markers used by the hook before the introduction of the terraform-docs markers
readonly old_insertion_marker_begin="<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->"
readonly old_insertion_marker_end="<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->"
function main {
common::initialize "$SCRIPT_DIR"
common::parse_cmdline "$@"
common::export_provided_env_vars "${ENV_VARS[@]}"
common::parse_and_export_env_vars
# Support for setting relative PATH to .terraform-docs.yml config.
for i in "${!ARGS[@]}"; do
ARGS[i]=${ARGS[i]/--config=/--config=$(pwd)\/}
done
# shellcheck disable=SC2153 # False positive
terraform_docs "${HOOK_CONFIG[*]}" "${ARGS[*]}" "${FILES[@]}"
}
#######################################################################
# Function to replace old markers with new markers affected files
# Globals:
# insertion_marker_begin - Standard insertion marker at beginning
# insertion_marker_end - Standard insertion marker at the end
# old_insertion_marker_begin - Old insertion marker at beginning
# old_insertion_marker_end - Old insertion marker at the end
# Arguments:
# file (string) filename to check
#######################################################################
function replace_old_markers {
local -r file=$1
# Determine the appropriate sed command based on the operating system (GNU sed or BSD sed)
sed --version &> /dev/null && SED_CMD=(sed -i) || SED_CMD=(sed -i '')
"${SED_CMD[@]}" -e "s/^${old_insertion_marker_begin}$/${insertion_marker_begin}/" "$file"
"${SED_CMD[@]}" -e "s/^${old_insertion_marker_end}$/${insertion_marker_end}/" "$file"
}
#######################################################################
# Wrapper around `terraform-docs` tool that checks and changes/creates
# (depending on provided hook_config) terraform documentation in
# Markdown
# Arguments:
# hook_config (string with array) arguments that configure hook behavior
# args (string with array) arguments that configure wrapped tool behavior
# files (array) filenames to check
#######################################################################
function terraform_docs {
local -r hook_config="$1"
local args="$2"
shift 2
local -a -r files=("$@")
if [[ ! $(command -v terraform-docs) ]]; then
echo "ERROR: terraform-docs is required by terraform_docs pre-commit hook but is not installed or in the system's PATH."
exit 1
fi
local -a paths
local index=0
local file_with_path
for file_with_path in "${files[@]}"; do
file_with_path="${file_with_path// /__REPLACED__SPACE__}"
paths[index]=$(dirname "$file_with_path")
((index += 1))
done
#
# Get hook settings
#
local output_file="README.md"
local output_mode="inject"
local use_path_to_file=false
local add_to_existing=false
local create_if_not_exist=false
local use_standard_markers=true
IFS=";" read -r -a configs <<< "$hook_config"
for c in "${configs[@]}"; do
IFS="=" read -r -a config <<< "$c"
key=${config[0]}
value=${config[1]}
case $key in
--path-to-file)
output_file=$value
use_path_to_file=true
;;
--add-to-existing-file)
add_to_existing=$value
;;
--create-file-if-not-exist)
create_if_not_exist=$value
;;
--use-standard-markers)
use_standard_markers=$value
common::colorify "yellow" "WARNING: --use-standard-markers is deprecated and will be removed in the future."
common::colorify "yellow" " All needed changes already done by the hook, feel free to remove --use-standard-markers setting from your pre-commit config"
;;
esac
done
if [[ $use_standard_markers == false ]]; then
# update the insertion markers to those used by pre-commit-terraform before v1.93
insertion_marker_begin="$old_insertion_marker_begin"
insertion_marker_end="$old_insertion_marker_end"
fi
# Override formatter if no config file set
if [[ "$args" != *"--config"* ]]; then
local tf_docs_formatter="md"
else
local config_file=${args#*--config}
config_file=${config_file#*=}
config_file=${config_file% *}
# Prioritize `.terraform-docs.yml` `output.file` over
# `--hook-config=--path-to-file=` if it set
local config_output_file
# Get latest non-commented `output.file` from `.terraform-docs.yml`
config_output_file=$(grep -A1000 -e '^output:$' "$config_file" | grep -E '^[[:space:]]+file:' | tail -n 1) || true
if [[ $config_output_file ]]; then
# Extract filename from `output.file` line
config_output_file=$(echo "$config_output_file" | awk -F':' '{print $2}' | tr -d '[:space:]"' | tr -d "'")
if [[ $use_path_to_file == true && "$config_output_file" != "$output_file" ]]; then
common::colorify "yellow" "NOTE: You set both '--hook-config=--path-to-file=$output_file' and 'output.file: $config_output_file' in '$config_file'"
common::colorify "yellow" " 'output.file' from '$config_file' will be used."
fi
output_file=$config_output_file
fi
# Use `.terraform-docs.yml` `output.mode` if it set
local config_output_mode
config_output_mode=$(grep -A1000 -e '^output:$' "$config_file" | grep -E '^[[:space:]]+mode:' | tail -n 1) || true
if [[ $config_output_mode ]]; then
# Extract mode from `output.mode` line
output_mode=$(echo "$config_output_mode" | awk -F':' '{print $2}' | tr -d '[:space:]"' | tr -d "'")
fi
# Suppress terraform_docs color
local config_file_no_color
config_file_no_color="$config_file$(date +%s).yml"
if [ "$PRE_COMMIT_COLOR" = "never" ] &&
[[ $(grep -e '^formatter:' "$config_file") == *"pretty"* ]] &&
[[ $(grep ' color: ' "$config_file") != *"false"* ]]; then
cp "$config_file" "$config_file_no_color"
echo -e "settings:\n color: false" >> "$config_file_no_color"
args=${args/$config_file/$config_file_no_color}
fi
fi
local dir_path
for dir_path in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
dir_path="${dir_path//__REPLACED__SPACE__/ }"
pushd "$dir_path" > /dev/null || continue
#
# Create file if it not exist and `--create-if-not-exist=true` provided
#
if $create_if_not_exist && [[ ! -f "$output_file" ]]; then
dir_have_tf_files="$(
find . -maxdepth 1 -type f | sed 's|.*\.||' | sort -u | grep -oE '^tf$|^tfvars$' ||
exit 0
)"
# if no TF files - skip dir
[ ! "$dir_have_tf_files" ] && popd > /dev/null && continue
dir="$(dirname "$output_file")"
mkdir -p "$dir"
# Use of insertion markers, where there is no existing README file
{
echo -e "# ${PWD##*/}\n"
echo "$insertion_marker_begin"
echo "$insertion_marker_end"
} >> "$output_file"
fi
# If file still not exist - skip dir
[[ ! -f "$output_file" ]] && popd > /dev/null && continue
replace_old_markers "$output_file"
#
# If `--add-to-existing-file=false` (default behavior), check if "hook markers" exist in file,
# and, if not, skip execution to avoid addition of terraform-docs section, as
# terraform-docs in 'inject' mode adds markers by default if they are not present
#
if [[ $add_to_existing == false ]]; then
have_marker=$(grep -o "$insertion_marker_begin" "$output_file") || unset have_marker
[[ ! $have_marker ]] && continue
fi
# shellcheck disable=SC2086
terraform-docs --output-mode="$output_mode" --output-file="$output_file" $tf_docs_formatter $args ./ > /dev/null
popd > /dev/null
done
# Cleanup
rm -f "$config_file_no_color"
}
[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@"