Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(terraform-docs): Add support for replace mode for TF 0.12+; Use native saving to file for TF 0.12+. Both requires terraform-docs v0.12.0+ which released in 2021. #705

Merged
merged 6 commits into from
Aug 29, 2024
31 changes: 20 additions & 11 deletions hooks/terraform_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,11 @@ function terraform_docs {
((index += 1))
done

local -r tmp_file=$(mktemp)

#
# 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
Expand Down Expand Up @@ -202,6 +201,14 @@ function terraform_docs {
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFYI: I'm still concerned with picking last key instead of first despite YAML requires keys to be unique — https://yaml.org/spec/1.2-old/spec.html#id2764044

The content of a mapping node is an unordered set of key: value node pairs, with the restriction that each of the keys is unique.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In YAML you can do next

foo: &anchor
    key: 111

bar: 
    <<: *anchor
    key: 222

I not sure what words in https://yaml.org/spec/1.2-old/spec.html#id2765878 exactly means, but it actually same to

foo:
    key: 111

bar: 
    key: 111
    key: 222

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might have worded it a bit ambiguous. What I mean is when you do grep -A1000 -e '^output:$' "$config_file" | grep -E '^[[:space:]]+mode:' | tail -n 1, you actually allow the below YAML within 1001 lines starting from the first match of ^output:$:

output:
    mode: 111

output: 
    mode: 222
    mode: 333

The output is what YAML expects to be unique node. Else YAML is incorrect.
From my point of view the first occurrence of output.mode key with value of 111 is what must be rendered as value for output.mode, whilst your implementation means the output.mode key with value 333 is what is taken as correct value.

Copy link
Collaborator

@yermulnik yermulnik Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given we're trying to employ as less third-party tools as feasible and to keep solution simple, I'd suggest we take first occurrence of output.mode since duplicates are not allowed.

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"
Expand Down Expand Up @@ -267,7 +274,7 @@ function terraform_docs {

if [[ "$terraform_docs_awk_file" == "0" ]]; then
# shellcheck disable=SC2086
terraform-docs --output-file="" $tf_docs_formatter $args ./ > "$tmp_file"
terraform-docs --output-mode="$output_mode" --output-file="$output_file" $tf_docs_formatter $args ./ > /dev/null
else
# Can't append extension for mktemp, so renaming instead
local tmp_file_docs
Expand All @@ -277,20 +284,22 @@ function terraform_docs {
tmp_file_docs_tf="$tmp_file_docs.tf"

awk -f "$terraform_docs_awk_file" ./*.tf > "$tmp_file_docs_tf"

local -r tmp_file=$(mktemp)
# shellcheck disable=SC2086
terraform-docs --output-file="" $tf_docs_formatter $args "$tmp_file_docs_tf" > "$tmp_file"
rm -f "$tmp_file_docs_tf"
fi

# Use of insertion markers to insert the terraform-docs output between the markers
# Replace content between markers with the placeholder - https://stackoverflow.com/questions/1212799/how-do-i-extract-lines-between-two-line-delimiters-in-perl#1212834
perl_expression="if (/$insertion_marker_begin/../$insertion_marker_end/) { print \$_ if /$insertion_marker_begin/; print \"I_WANT_TO_BE_REPLACED\\n\$_\" if /$insertion_marker_end/;} else { print \$_ }"
perl -i -ne "$perl_expression" "$output_file"
# Use of insertion markers to insert the terraform-docs output between the markers
# Replace content between markers with the placeholder - https://stackoverflow.com/questions/1212799/how-do-i-extract-lines-between-two-line-delimiters-in-perl#1212834
perl_expression="if (/$insertion_marker_begin/../$insertion_marker_end/) { print \$_ if /$insertion_marker_begin/; print \"I_WANT_TO_BE_REPLACED\\n\$_\" if /$insertion_marker_end/;} else { print \$_ }"
perl -i -ne "$perl_expression" "$output_file"

# Replace placeholder with the content of the file
perl -i -e 'open(F, "'"$tmp_file"'"); $f = join "", <F>; while(<>){if (/I_WANT_TO_BE_REPLACED/) {print $f} else {print $_};}' "$output_file"
# Replace placeholder with the content of the file
perl -i -e 'open(F, "'"$tmp_file"'"); $f = join "", <F>; while(<>){if (/I_WANT_TO_BE_REPLACED/) {print $f} else {print $_};}' "$output_file"

rm -f "$tmp_file"
rm -f "$tmp_file"
fi

popd > /dev/null
done
Expand Down
Loading