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: Add an option --tf-version to terraform_docs, terraform_fmt, and terraform_validate #194

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
<a name="unreleased"></a>
## [Unreleased]


- feat: Add option for using `tfenv` to switch terraform versions in terraform_docs, terraform_fmt, terraform_validate

<a name="v1.49.0"></a>
## [v1.49.0] - 2021-04-20
Expand Down Expand Up @@ -145,7 +145,7 @@ All notable changes to this project will be documented in this file.

- fix: Change terraform_validate hook functionality for subdirectories with terraform files ([#100](https://github.com/antonbabenko/pre-commit-terraform/issues/100))

###
###

configuration for the appropriate working directory.

Expand Down
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@
* [`TFSec`](https://github.com/liamg/tfsec) required for `terraform_tfsec` hook.
* [`coreutils`](https://formulae.brew.sh/formula/coreutils) required for `terraform_validate` hook on macOS (due to use of `realpath`).
* [`checkov`](https://github.com/bridgecrewio/checkov) required for `checkov` hook.
* [`tfenv`](https://github.com/tfutils/tfenv) if you wish to specify a desired version of terraform for the `terraform_fmt`, `terraform_validate`, or `terraform_docs` hooks.

or build and use the Docker image locally as mentioned below in the `Run` section.

##### MacOS

```bash
brew install pre-commit gawk terraform-docs tflint tfsec coreutils checkov
brew install pre-commit gawk terraform-docs tflint tfsec coreutils checkov tfenv
```

##### Ubuntu 18.04
Expand All @@ -35,6 +36,8 @@ curl -L "$(curl -s https://api.github.com/repos/tfsec/tfsec/releases/latest | gr
python3.7 -m pip install -U checkov
```

`tfenv` installation varies depending on distribution, see full install instructions here: https://github.com/tfutils/tfenv#manual

### 2. Install the pre-commit hook globally
Note: not needed if you use the Docker image

Expand Down Expand Up @@ -72,9 +75,9 @@ or you can also build and use the provided Docker container, which wraps all dep
```bash
# first building it
docker build -t pre-commit .
# and then running it in the folder
# and then running it in the folder
# with the terraform code you want to check by executing
docker run -v $(pwd):/lint -w /lint pre-commit run -a
docker run -v $(pwd):/lint -w /lint pre-commit run -a
```

## Available Hooks
Expand All @@ -96,6 +99,16 @@ There are several [pre-commit](https://pre-commit.com/) hooks to keep Terraform

Check the [source file](https://github.com/antonbabenko/pre-commit-terraform/blob/master/.pre-commit-hooks.yaml) to know arguments used for each hook.

## Using a specific terraform version via `tfenv`

Hooks which call terraform directly (`terraform_fmt`, `terraform_validate`, `terraform_docs`) support the `--tf-version` argument to optionally ensure that the correct version of terraform is used.

```yaml
hooks:
- id: terraform_fmt
args: ['--tf-version=0.12.18']
```

## Notes about terraform_docs hooks

1. `terraform_docs` and `terraform_docs_without_aggregate_type_defaults` will insert/update documentation generated by [terraform-docs](https://github.com/terraform-docs/terraform-docs) framed by markers:
Expand Down
21 changes: 21 additions & 0 deletions lib_tfenv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
function switchTfEnv() {
TARGET_VERSION="$1"

# Read current terraform version
CURRENT_VERSION=$(tfenv list | sed -nr 's/^\* ([0-9\-\.]+) .*/\1/p')
echo "Current version is set to '$CURRENT_VERSION', switching to '$TARGET_VERSION'"

# Install and switch to required version
tfenv install "$TARGET_VERSION"
tfenv use "$TARGET_VERSION"

# Auto-cleanup on exit
trap restoreTfEnv EXIT
}

function restoreTfEnv() {
# Restore
echo "Restoring version to '$CURRENT_VERSION'"
tfenv use "$CURRENT_VERSION"
}
14 changes: 12 additions & 2 deletions terraform_docs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ set -eo pipefail
main() {
initialize_
parse_cmdline_ "$@"

# If a specific terraform version was specified, switch to it. The tfenv lib will auto-restore on exit
[ "$TFVER" != "" ] && . "$_SCRIPT_DIR/lib_tfenv" && switchTfEnv "$TFVER"

terraform_docs_ "${ARGS[*]}" "${FILES[@]}"
}

Expand All @@ -27,7 +31,7 @@ initialize_() {

parse_cmdline_() {
declare argv
argv=$(getopt -o a: --long args: -- "$@") || return
argv=$(getopt -o a:t: --long args:,tf-version: -- "$@") || return
eval "set -- $argv"

for argv; do
Expand All @@ -37,6 +41,11 @@ parse_cmdline_() {
ARGS+=("$1")
shift
;;
-t | --tf-version)
shift
TFVER="$1"
shift
;;
--)
shift
FILES=("$@")
Expand Down Expand Up @@ -311,7 +320,8 @@ EOF

}

# global arrays
# global variables
declare TFVER=""
declare -a ARGS=()
declare -a FILES=()

Expand Down
104 changes: 81 additions & 23 deletions terraform_fmt.sh
Original file line number Diff line number Diff line change
@@ -1,34 +1,92 @@
#!/usr/bin/env bash
set -e
set -eo pipefail

declare -a paths
declare -a tfvars_files
main() {
initialize_
parse_cmdline_ "$@"

index=0
# If a specific terraform version was specified, switch to it. The tfenv lib will auto-restore on exit
[ "$TFVER" != "" ] && . "$_SCRIPT_DIR/lib_tfenv" && switchTfEnv "$TFVER"

for file_with_path in "$@"; do
file_with_path="${file_with_path// /__REPLACED__SPACE__}"
terraform_fmt_ "${FILES[@]}"
}

paths[index]=$(dirname "$file_with_path")
initialize_() {
# get directory containing this script
local dir
local source
source="${BASH_SOURCE[0]}"
while [[ -L $source ]]; do # resolve $source until the file is no longer a symlink
dir="$(cd -P "$(dirname "$source")" > /dev/null && pwd)"
source="$(readlink "$source")"
# if $source was a relative symlink, we need to resolve it relative to the path where the symlink file was located
[[ $source != /* ]] && source="$dir/$source"
done
_SCRIPT_DIR="$(dirname "$source")"

if [[ "$file_with_path" == *".tfvars" ]]; then
tfvars_files+=("$file_with_path")
fi
# source getopt function
# shellcheck source=lib_getopt
. "$_SCRIPT_DIR/lib_getopt"
}

let "index+=1"
done
parse_cmdline_() {
declare argv
argv=$(getopt -o t: --long tf-version: -- "$@") || return
eval "set -- $argv"

for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
path_uniq="${path_uniq//__REPLACED__SPACE__/ }"
for argv; do
case $argv in
-t | --tf-version)
shift
TFVER="$1"
shift
;;
--)
shift
FILES=("$@")
break
;;
esac
done
}

pushd "$path_uniq" > /dev/null
terraform fmt
popd > /dev/null
done
terraform_fmt_() {
local -a -r files=("$@")
declare -a paths
declare -a tfvars_files

# terraform.tfvars are excluded by `terraform fmt`
for tfvars_file in "${tfvars_files[@]}"; do
tfvars_file="${tfvars_file//__REPLACED__SPACE__/ }"
index=0

terraform fmt "$tfvars_file"
done
for file_with_path in "${files[@]}"; do
file_with_path="${file_with_path// /__REPLACED__SPACE__}"

paths[index]=$(dirname "$file_with_path")

if [[ "$file_with_path" == *".tfvars" ]]; then
tfvars_files+=("$file_with_path")
fi

let "index+=1"
done

for path_uniq in $(echo "${paths[*]}" | tr ' ' '\n' | sort -u); do
path_uniq="${path_uniq//__REPLACED__SPACE__/ }"

pushd "$path_uniq" > /dev/null
terraform fmt
popd > /dev/null
done

# terraform.tfvars are excluded by `terraform fmt`
for tfvars_file in "${tfvars_files[@]}"; do
tfvars_file="${tfvars_file//__REPLACED__SPACE__/ }"

terraform fmt "$tfvars_file"
done
}

# global variables
declare TFVER=""
declare -a FILES=()

[[ ${BASH_SOURCE[0]} != "$0" ]] || main "$@"
14 changes: 12 additions & 2 deletions terraform_validate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ export AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION:-us-east-1}
main() {
initialize_
parse_cmdline_ "$@"

# If a specific terraform version was specified, switch to it. The tfenv lib will auto-restore on exit
[ "$TFVER" != "" ] && . "$_SCRIPT_DIR/lib_tfenv" && switchTfEnv "$TFVER"

terraform_validate_
}

Expand All @@ -30,7 +34,7 @@ initialize_() {

parse_cmdline_() {
declare argv
argv=$(getopt -o e:a: --long envs:,args: -- "$@") || return
argv=$(getopt -o e:a:t: --long envs:,args:,tf-version: -- "$@") || return
eval "set -- $argv"

for argv; do
Expand All @@ -45,6 +49,11 @@ parse_cmdline_() {
ENVS+=("$1")
shift
;;
-t | --tf-version)
shift
TFVER="$1"
shift
;;
--)
shift
FILES=("$@")
Expand Down Expand Up @@ -121,7 +130,8 @@ terraform_validate_() {
fi
}

# global arrays
# global variables
declare TFVER=""
declare -a ARGS
declare -a ENVS
declare -a FILES
Expand Down