Added support for terraform_docs for Terraform 0.12 (#45)

This commit is contained in:
Anton Babenko 2019-06-17 12:47:06 +02:00 committed by GitHub
commit 8cddce38b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 115 additions and 8 deletions

View file

@ -6,10 +6,10 @@
### Step 1
On MacOSX install the pre-commit package
On MacOSX install the `pre-commit` and `awk` (required for Terraform 0.12) package
```bash
brew install pre-commit
brew install pre-commit awk
```
For other operating systems check the [official documentation](http://pre-commit.com/#install)
@ -21,10 +21,10 @@ Step into the repository you want to have the pre-commit hooks installed and run
```bash
cat <<EOF > .pre-commit-config.yaml
- repo: git://github.com/antonbabenko/pre-commit-terraform
rev: v1.12.0
rev: v1.13.0
hooks:
- id: terraform_fmt
# - id: terraform_docs # terraform-docs is not working with Terraform 0.12 yet (read note in README)
- id: terraform_docs
EOF
```
@ -73,7 +73,7 @@ Check the [source file](https://github.com/antonbabenko/pre-commit-terraform/blo
1. It is possible to pass additional arguments to shell scripts when using `terraform_docs` and `terraform_docs_without_aggregate_type_defaults`. Send pull-request with the new hook if there is something missing.
1. `terraform-docs` is not working with Terraform 0.12 yet (see [issue #62](https://github.com/segmentio/terraform-docs/issues/62)), so remember to disable `terraform_docs`, `terraform_docs_replace` and `terraform_docs_without_aggregate_type_defaults` hooks in your `.pre-commit-config.yaml`
1. `terraform-docs` works with Terraform 0.12 but support is hackish (it requires `awk` to be installed) and may contain bugs. You can follow the native support of Terraform 0.12 in `terraform-docs` in [issue #62](https://github.com/segmentio/terraform-docs/issues/62).
## Notes for developers

View file

@ -25,12 +25,25 @@ main() {
esac
done
terraform_docs "$args" "$files"
local hack_terraform_docs=$(terraform version | head -1 | grep -c 0.12)
if [[ "$hack_terraform_docs" == "1" ]]; then
which awk 2>&1 >/dev/null || ( echo "awk is required for terraform-docs hack to work with Terraform 0.12"; exit 1)
TMP_AWK_FILE="$(mktemp --tmpdir terraform-docs-XXXXXXXXXX.awk)"
terraform_docs_awk $TMP_AWK_FILE
terraform_docs "$TMP_AWK_FILE" "$args" "$files"
rm -f "$TMP_AWK_FILE"
else
terraform_docs "0" "$args" "$files"
fi
}
terraform_docs() {
readonly args="$1"
readonly files="$2"
readonly terraform_docs_awk_file="$1"
readonly args="$2"
readonly files="$3"
declare -a paths
declare -a tfvars_files
@ -62,7 +75,14 @@ terraform_docs() {
continue
fi
if [[ "$terraform_docs_awk_file" == "0" ]]; then
terraform-docs $args md ./ > "$tmp_file"
else
TMP_FILE="$(mktemp --tmpdir terraform-docs-XXXXXXXXXX.tf)"
awk -f "$terraform_docs_awk_file" ./*.tf > "$TMP_FILE"
terraform-docs $args md "$TMP_FILE" > "$tmp_file"
rm -f "$TMP_FILE"
fi
# 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 -i -ne 'if (/BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/../END OF PRE-COMMIT-TERRAFORM DOCS HOOK/) { print $_ if /BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK/; print "I_WANT_TO_BE_REPLACED\n$_" if /END OF PRE-COMMIT-TERRAFORM DOCS HOOK/;} else { print $_ }' "$text_file"
@ -76,6 +96,93 @@ terraform_docs() {
done
}
terraform_docs_awk() {
readonly output_file=$1
cat <<"EOF" > $output_file
# This script converts Terraform 0.12 variables/outputs to something suitable for `terraform-docs`
# As of terraform-docs v0.6.0, HCL2 is not supported. This script is a *dirty hack* to get around it.
# https://github.com/segmentio/terraform-docs/
# https://github.com/segmentio/terraform-docs/issues/62
{
if ( /\{/ ) {
braceCnt++
}
if ( /\}/ ) {
braceCnt--
}
# [START] variable or output block started
if ($0 ~ /(variable|output) "(.*?)"/) {
# [CLOSE] "default" block
if (blockDefCnt > 0) {
blockDefCnt = 0
}
blockCnt++
print $0
}
# [START] multiline default statement started
if (blockCnt > 0) {
if ($1 == "default") {
print $0
if ($NF ~ /[\[\(\{]/) {
blockDefCnt++
blockDefStart=1
}
}
}
# [PRINT] single line "description"
if (blockDefCnt == 0) {
if ($1 == "description") {
# [CLOSE] "default" block
if (blockDefCnt > 0) {
blockDefCnt = 0
}
print $0
}
}
# [PRINT] single line "type"
if (blockCnt > 0) {
if ($1 == "type" ) {
# [CLOSE] "default" block
if (blockDefCnt > 0) {
blockDefCnt = 0
}
type=$3
if (type ~ "object") {
print " type = \"object\""
} else {
print " type = \"" $3 "\""
}
}
}
# [CLOSE] variable/output block
if (blockCnt > 0) {
if (braceCnt == 0 && blockCnt > 0) {
blockCnt--
print $0
}
}
# [PRINT] Multiline "default" statement
if (blockCnt > 0 && blockDefCnt > 0) {
if (blockDefStart == 1) {
blockDefStart = 0
} else {
print $0
}
}
}
EOF
}
getopt() {
# pure-getopt, a drop-in replacement for GNU getopt in pure Bash.
# version 1.4.3