From da0973662585574af4bed5e1e1d8798fa6c3b4b0 Mon Sep 17 00:00:00 2001 From: Peter Halliday Date: Sat, 28 Oct 2023 21:39:58 -0500 Subject: [PATCH 1/3] Add terraform and terragrunt testing --- .pre-commit-hooks.yaml | 16 ++++++++++ hooks/terraform_test.sh | 54 ++++++++++++++++++++++++++++++++ hooks/terragrunt_test.sh | 67 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100755 hooks/terraform_test.sh create mode 100755 hooks/terragrunt_test.sh diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index 7b5152ba4..e6671948f 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -77,6 +77,22 @@ files: (\.hcl)$ exclude: \.terraform\/.*$ +- id: terraform_test + name: Terraform test + description: Runs all terraform tests + entry: hooks/terraform_test.sh + language: script + files: (\.tf)$ + exclude: \.terraform\/.*$ + +- id: terragrunt_test + name: Terragrunt test + description: Runs all terraform tests + entry: hooks/terragrunt_test.sh + language: script + files: (\.tf)$d + exclude: \.terraform\/.*$ + - id: terragrunt_validate name: Terragrunt validate description: Validates all Terragrunt configuration files. diff --git a/hooks/terraform_test.sh b/hooks/terraform_test.sh new file mode 100755 index 000000000..291bdcd51 --- /dev/null +++ b/hooks/terraform_test.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +set -eo pipefail + +# globals variables +# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines +readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +# shellcheck source=_common.sh +. "$SCRIPT_DIR/_common.sh" + +function main { + common::initialize "$SCRIPT_DIR" + common::parse_cmdline "$@" + common::export_provided_env_vars "${ENV_VARS[@]}" + common::parse_and_export_env_vars + + # Suppress terraform test color + if [ "$PRE_COMMIT_COLOR" = "never" ]; then + ARGS+=("-no-color") + fi + + # shellcheck disable=SC2153 # False positive + common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" +} + +####################################################################### +# Unique part of `common::per_dir_hook`. The function is executed in loop +# on each provided dir path. Run wrapped tool with specified arguments +# Arguments: +# dir_path (string) PATH to dir relative to git repo root. +# Can be used in error logging +# change_dir_in_unique_part (string/false) Modifier which creates +# possibilities to use non-common chdir strategies. +# Availability depends on hook. +# args (array) arguments that configure wrapped tool behavior +# Outputs: +# If failed - print out hook checks status +####################################################################### +function per_dir_hook_unique_part { + # shellcheck disable=SC2034 # Unused var. + local -r dir_path="$1" + # shellcheck disable=SC2034 # Unused var. + local -r change_dir_in_unique_part="$2" + shift 2 + local -a -r args=("$@") + + # pass the arguments to hook + terraform test "${args[@]}" + + # return exit code to common::per_dir_hook + local exit_code=$? + return $exit_code +} + +[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@" diff --git a/hooks/terragrunt_test.sh b/hooks/terragrunt_test.sh new file mode 100755 index 000000000..677b6b0db --- /dev/null +++ b/hooks/terragrunt_test.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash +set -eo pipefail + +# globals variables +# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines +readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" +# shellcheck source=_common.sh +. "$SCRIPT_DIR/_common.sh" + +function main { + common::initialize "$SCRIPT_DIR" + common::parse_cmdline "$@" + common::export_provided_env_vars "${ENV_VARS[@]}" + common::parse_and_export_env_vars + # JFYI: terragrunt test color already suppressed via PRE_COMMIT_COLOR=never + + # shellcheck disable=SC2153 # False positive + common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" +} + +####################################################################### +# Unique part of `common::per_dir_hook`. The function is executed in loop +# on each provided dir path. Run wrapped tool with specified arguments +# Arguments: +# dir_path (string) PATH to dir relative to git repo root. +# Can be used in error logging +# change_dir_in_unique_part (string/false) Modifier which creates +# possibilities to use non-common chdir strategies. +# Availability depends on hook. +# args (array) arguments that configure wrapped tool behavior +# Outputs: +# If failed - print out hook checks status +####################################################################### +function per_dir_hook_unique_part { + # shellcheck disable=SC2034 # Unused var. + local -r dir_path="$1" + # shellcheck disable=SC2034 # Unused var. + local -r change_dir_in_unique_part="$2" + shift 2 + local -a -r args=("$@") + + # pass the arguments to hook + terragrunt test "${args[@]}" + + # return exit code to common::per_dir_hook + local exit_code=$? + return $exit_code +} + +####################################################################### +# Unique part of `common::per_dir_hook`. The function is executed one time +# in the root git repo +# Arguments: +# args (array) arguments that configure wrapped tool behavior +####################################################################### +function run_hook_on_whole_repo { + local -a -r args=("$@") + + # pass the arguments to hook + terragrunt test "$(pwd)" "${args[@]}" + + # return exit code to common::per_dir_hook + local exit_code=$? + return $exit_code +} + +[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@" From d119e33007aded4fdc13f407e88363f2183b232c Mon Sep 17 00:00:00 2001 From: Peter Halliday Date: Sat, 28 Oct 2023 21:39:58 -0500 Subject: [PATCH 2/3] Add terraform and terragrunt testing --- .pre-commit-hooks.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index e6671948f..bb87abcbb 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -90,7 +90,11 @@ description: Runs all terraform tests entry: hooks/terragrunt_test.sh language: script +<<<<<<< HEAD files: (\.tf)$d +======= + files: (\.tf)$ +>>>>>>> c943481 (Add terraform and terragrunt testing) exclude: \.terraform\/.*$ - id: terragrunt_validate From 42d470d89394795b0a6e272fe414ac7e02d433e0 Mon Sep 17 00:00:00 2001 From: Peter Halliday Date: Fri, 3 Nov 2023 16:57:17 -0500 Subject: [PATCH 3/3] update after PR comments --- .pre-commit-hooks.yaml | 14 +-------- README.md | 22 ++++++++++++- hooks/terraform_test.sh | 18 ++--------- hooks/terragrunt_test.sh | 67 ---------------------------------------- 4 files changed, 25 insertions(+), 96 deletions(-) delete mode 100755 hooks/terragrunt_test.sh diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml index bb87abcbb..7ac6c99f3 100644 --- a/.pre-commit-hooks.yaml +++ b/.pre-commit-hooks.yaml @@ -82,19 +82,7 @@ description: Runs all terraform tests entry: hooks/terraform_test.sh language: script - files: (\.tf)$ - exclude: \.terraform\/.*$ - -- id: terragrunt_test - name: Terragrunt test - description: Runs all terraform tests - entry: hooks/terragrunt_test.sh - language: script -<<<<<<< HEAD - files: (\.tf)$d -======= - files: (\.tf)$ ->>>>>>> c943481 (Add terraform and terragrunt testing) + files: (\.tf|\.tfvars|\.terraform\.lock\.hcl||\.terraform\.lock\.hcl||\.terraform\.lock\.json)$ exclude: \.terraform\/.*$ - id: terragrunt_validate diff --git a/README.md b/README.md index 04a67055f..a0b1bc8d4 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ If you are using `pre-commit-terraform` already or want to support its developme * [terraform\_docs\_replace (deprecated)](#terraform_docs_replace-deprecated) * [terraform\_fmt](#terraform_fmt) * [terraform\_providers\_lock](#terraform_providers_lock) + * [terraform\_test](#terraform_test) * [terraform\_tflint](#terraform_tflint) * [terraform\_tfsec](#terraform_tfsec) * [terraform\_validate](#terraform_validate) @@ -271,9 +272,10 @@ There are several [pre-commit](https://pre-commit.com/) hooks to keep Terraform | `terraform_docs_without_`
`aggregate_type_defaults` | Inserts input and output documentation into `README.md` without aggregate type defaults. Hook notes same as for [terraform_docs](#terraform_docs) | `terraform-docs` | | `terraform_fmt` | Reformat all Terraform configuration files to a canonical format. [Hook notes](#terraform_fmt) | - | | `terraform_providers_lock` | Updates provider signatures in [dependency lock files](https://www.terraform.io/docs/cli/commands/providers/lock.html). [Hook notes](#terraform_providers_lock) | - | +| `terraform_test` | Runs any Terraform Tests, which requires Terraform 1.6 and above. [Hook notes](#terraform_test) | | `terraform_tflint` | Validates all Terraform configuration files with [TFLint](https://github.com/terraform-linters/tflint). [Available TFLint rules](https://github.com/terraform-linters/tflint/tree/master/docs/rules#rules). [Hook notes](#terraform_tflint). | `tflint` | | `terraform_tfsec` | [TFSec](https://github.com/aquasecurity/tfsec) static analysis of terraform templates to spot potential security issues. [Hook notes](#terraform_tfsec) | `tfsec` | -| `terraform_validate` | Validates all Terraform configuration files. [Hook notes](#terraform_validate) | `jq`, only for `--retry-once-with-cleanup` flag | +| `terraform_validate` sd | Validates all Terraform configuration files. [Hook notes](#terraform_validate) | `jq`, only for `--retry-once-with-cleanup` flag | | `terragrunt_fmt` | Reformat all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) to a canonical format. | `terragrunt` | | `terragrunt_validate` | Validates all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) | `terragrunt` | | `terraform_wrapper_module_for_each` | Generates Terraform wrappers with `for_each` in module. [Hook notes](#terraform_wrapper_module_for_each) | `hcledit` | @@ -645,6 +647,24 @@ To replicate functionality in `terraform_docs` hook: - --tf-init-args=-upgrade ``` +### terraform_test + +1. `terraform_test` supports custom arguments so you can set the test directory, set a variable file, change output to JSON and change the verbosity, filtering which tests runs, and set individual variables. + + Example: + + ```yaml + - id: terraform_test + args: + - --args=-test-directory=path + - --arg=-filter=testfile + - --args=-json + - --arg=-verbose + - --arg=-var-file=filename + - --arg=-var=variable + ``` + +2. `terraform_test` only runs per repository. ### terraform_tflint diff --git a/hooks/terraform_test.sh b/hooks/terraform_test.sh index 291bdcd51..8af7203f7 100755 --- a/hooks/terraform_test.sh +++ b/hooks/terraform_test.sh @@ -23,24 +23,12 @@ function main { } ####################################################################### -# Unique part of `common::per_dir_hook`. The function is executed in loop -# on each provided dir path. Run wrapped tool with specified arguments +# Unique part of `common::per_dir_hook`. The function is executed one time +# in the root git repo # Arguments: -# dir_path (string) PATH to dir relative to git repo root. -# Can be used in error logging -# change_dir_in_unique_part (string/false) Modifier which creates -# possibilities to use non-common chdir strategies. -# Availability depends on hook. # args (array) arguments that configure wrapped tool behavior -# Outputs: -# If failed - print out hook checks status ####################################################################### -function per_dir_hook_unique_part { - # shellcheck disable=SC2034 # Unused var. - local -r dir_path="$1" - # shellcheck disable=SC2034 # Unused var. - local -r change_dir_in_unique_part="$2" - shift 2 +function run_hook_on_whole_repo { local -a -r args=("$@") # pass the arguments to hook diff --git a/hooks/terragrunt_test.sh b/hooks/terragrunt_test.sh deleted file mode 100755 index 677b6b0db..000000000 --- a/hooks/terragrunt_test.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash -set -eo pipefail - -# globals variables -# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines -readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)" -# shellcheck source=_common.sh -. "$SCRIPT_DIR/_common.sh" - -function main { - common::initialize "$SCRIPT_DIR" - common::parse_cmdline "$@" - common::export_provided_env_vars "${ENV_VARS[@]}" - common::parse_and_export_env_vars - # JFYI: terragrunt test color already suppressed via PRE_COMMIT_COLOR=never - - # shellcheck disable=SC2153 # False positive - common::per_dir_hook "$HOOK_ID" "${#ARGS[@]}" "${ARGS[@]}" "${FILES[@]}" -} - -####################################################################### -# Unique part of `common::per_dir_hook`. The function is executed in loop -# on each provided dir path. Run wrapped tool with specified arguments -# Arguments: -# dir_path (string) PATH to dir relative to git repo root. -# Can be used in error logging -# change_dir_in_unique_part (string/false) Modifier which creates -# possibilities to use non-common chdir strategies. -# Availability depends on hook. -# args (array) arguments that configure wrapped tool behavior -# Outputs: -# If failed - print out hook checks status -####################################################################### -function per_dir_hook_unique_part { - # shellcheck disable=SC2034 # Unused var. - local -r dir_path="$1" - # shellcheck disable=SC2034 # Unused var. - local -r change_dir_in_unique_part="$2" - shift 2 - local -a -r args=("$@") - - # pass the arguments to hook - terragrunt test "${args[@]}" - - # return exit code to common::per_dir_hook - local exit_code=$? - return $exit_code -} - -####################################################################### -# Unique part of `common::per_dir_hook`. The function is executed one time -# in the root git repo -# Arguments: -# args (array) arguments that configure wrapped tool behavior -####################################################################### -function run_hook_on_whole_repo { - local -a -r args=("$@") - - # pass the arguments to hook - terragrunt test "$(pwd)" "${args[@]}" - - # return exit code to common::per_dir_hook - local exit_code=$? - return $exit_code -} - -[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@"