Skip to content

Commit ef7a0f2

Browse files
authored
feat: Added support for tfupdate to update version constraints in Terraform configurations (antonbabenko#342)
1 parent 35c4550 commit ef7a0f2

File tree

4 files changed

+120
-3
lines changed

4 files changed

+120
-3
lines changed

.pre-commit-hooks.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,13 @@
111111
files: \.tf$
112112
exclude: \.terraform\/.*$
113113
require_serial: true
114+
115+
- id: tfupdate
116+
name: tfupdate
117+
description: Runs tfupdate on Terraform templates.
118+
language: script
119+
entry: hooks/tfupdate.sh
120+
args:
121+
- --args=terraform
122+
files: \.tf$
123+
require_serial: true

Dockerfile

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ ARG TERRAGRUNT_VERSION=${TERRAGRUNT_VERSION:-false}
3434
ARG TERRASCAN_VERSION=${TERRASCAN_VERSION:-false}
3535
ARG TFLINT_VERSION=${TFLINT_VERSION:-false}
3636
ARG TFSEC_VERSION=${TFSEC_VERSION:-false}
37+
ARG TFUPDATE_VERSION=${TFUPDATE_VERSION:-false}
3738

3839

3940
# Tricky thing to install all tools by set only one arg.
@@ -47,7 +48,8 @@ RUN if [ "$INSTALL_ALL" != "false" ]; then \
4748
echo "export TERRAGRUNT_VERSION=latest" >> /.env && \
4849
echo "export TERRASCAN_VERSION=latest" >> /.env && \
4950
echo "export TFLINT_VERSION=latest" >> /.env && \
50-
echo "export TFSEC_VERSION=latest" >> /.env \
51+
echo "export TFSEC_VERSION=latest" >> /.env && \
52+
echo "export TFUPDATE_VERSION=latest" >> /.env \
5153
; else \
5254
touch /.env \
5355
; fi
@@ -126,6 +128,16 @@ RUN . /.env && \
126128
) && chmod +x tfsec \
127129
; fi
128130

131+
# TFUpdate
132+
RUN . /.env && \
133+
if [ "$TFUPDATE_VERSION" != "false" ]; then \
134+
( \
135+
TFUPDATE_RELEASES="https://api.github.com/repos/minamijoyo/tfupdate/releases" && \
136+
[ "$TFUPDATE_VERSION" = "latest" ] && curl -L "$(curl -s ${TFUPDATE_RELEASES}/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tgz \
137+
|| curl -L "$(curl -s ${TFUPDATE_RELEASES} | grep -o -E -m 1 "https://.+?${TFUPDATE_VERSION}_linux_amd64.tar.gz")" > tfupdate.tgz \
138+
) && tar -xzf tfupdate.tgz tfupdate && rm tfupdate.tgz \
139+
; fi
140+
129141
# Checking binaries versions and write it to debug file
130142
RUN . /.env && \
131143
F=tools_versions_info && \
@@ -138,6 +150,7 @@ RUN . /.env && \
138150
(if [ "$TERRASCAN_VERSION" != "false" ]; then echo "terrascan $(./terrascan version)" >> $F; else echo "terrascan SKIPPED" >> $F ; fi) && \
139151
(if [ "$TFLINT_VERSION" != "false" ]; then ./tflint --version >> $F; else echo "tflint SKIPPED" >> $F ; fi) && \
140152
(if [ "$TFSEC_VERSION" != "false" ]; then echo "tfsec $(./tfsec --version)" >> $F; else echo "tfsec SKIPPED" >> $F ; fi) && \
153+
(if [ "$TFUPDATE_VERSION" != "false" ]; then echo "tfupdate $(./tfupdate --version)" >> $F; else echo "tfupdate SKIPPED" >> $F ; fi) && \
141154
echo -e "\n\n" && cat $F && echo -e "\n\n"
142155

143156

README.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ If you are using `pre-commit-terraform` already or want to support its developme
4646
* [terraform_tfsec](#terraform_tfsec)
4747
* [terraform_validate](#terraform_validate)
4848
* [terrascan](#terrascan)
49+
* [tfupdate](#tfupdate)
4950
* [Authors](#authors)
5051
* [License](#license)
5152
* [Additional terms of use for users from Russia and Belarus](#additional-terms-of-use-for-users-from-russia-and-belarus)
@@ -65,6 +66,7 @@ If you are using `pre-commit-terraform` already or want to support its developme
6566
* [`TFSec`](https://github.com/liamg/tfsec) required for `terraform_tfsec` hook.
6667
* [`infracost`](https://github.com/infracost/infracost) required for `infracost_breakdown` hook.
6768
* [`jq`](https://github.com/stedolan/jq) required for `infracost_breakdown` hook.
69+
* [`tfupdate`](https://github.com/minamijoyo/tfupdate) required for `tfupdate` hook.
6870

6971
<details><summary><b>Docker</b></summary><br>
7072

@@ -101,6 +103,7 @@ docker build -t pre-commit-terraform \
101103
--build-arg TERRASCAN_VERSION=1.10.0 \
102104
--build-arg TFLINT_VERSION=0.31.0 \
103105
--build-arg TFSEC_VERSION=latest \
106+
--build-arg TFUPDATE_VERSION=latest \
104107
.
105108
```
106109

@@ -114,7 +117,7 @@ Set `-e PRE_COMMIT_COLOR=never` to disable the color output in `pre-commit`.
114117
[`coreutils`](https://formulae.brew.sh/formula/coreutils) is required for hooks on MacOS (due to use of `realpath`).
115118

116119
```bash
117-
brew install pre-commit terraform-docs tflint tfsec coreutils checkov terrascan infracost jq
120+
brew install pre-commit terraform-docs tflint tfsec coreutils checkov terrascan infracost tfupdate jq
118121
```
119122

120123
</details>
@@ -135,6 +138,7 @@ curl -L "$(curl -s https://api.github.com/repos/aquasecurity/tfsec/releases/late
135138
curl -L "$(curl -s https://api.github.com/repos/accurics/terrascan/releases/latest | grep -o -E -m 1 "https://.+?_Linux_x86_64.tar.gz")" > terrascan.tar.gz && tar -xzf terrascan.tar.gz terrascan && rm terrascan.tar.gz && sudo mv terrascan /usr/bin/ && terrascan init
136139
sudo apt install -y jq && \
137140
curl -L "$(curl -s https://api.github.com/repos/infracost/infracost/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz && tar -xzf infracost.tgz && rm infracost.tgz && sudo mv infracost-linux-amd64 /usr/bin/infracost && infracost register
141+
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/tfupdate/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tar.gz && tar -xzf tfupdate.tar.gz tfupdate && rm tfupdate.tar.gz && sudo mv tfupdate /usr/bin/
138142
```
139143

140144
</details>
@@ -154,6 +158,7 @@ curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/release
154158
curl -L "$(curl -s https://api.github.com/repos/aquasecurity/tfsec/releases/latest | grep -o -E -m 1 "https://.+?tfsec-linux-amd64")" > tfsec && chmod +x tfsec && sudo mv tfsec /usr/bin/
155159
sudo apt install -y jq && \
156160
curl -L "$(curl -s https://api.github.com/repos/infracost/infracost/releases/latest | grep -o -E -m 1 "https://.+?-linux-amd64.tar.gz")" > infracost.tgz && tar -xzf infracost.tgz && rm infracost.tgz && sudo mv infracost-linux-amd64 /usr/bin/infracost && infracost register
161+
curl -L "$(curl -s https://api.github.com/repos/minamijoyo/tfupdate/releases/latest | grep -o -E -m 1 "https://.+?_linux_amd64.tar.gz")" > tfupdate.tar.gz && tar -xzf tfupdate.tar.gz tfupdate && rm tfupdate.tar.gz && sudo mv tfupdate /usr/bin/
157162
```
158163

159164
</details>
@@ -227,7 +232,8 @@ There are several [pre-commit](https://pre-commit.com/) hooks to keep Terraform
227232
| `terraform_validate` | Validates all Terraform configuration files. [Hook notes](#terraform_validate) | - |
228233
| `terragrunt_fmt` | Reformat all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) to a canonical format. | `terragrunt` |
229234
| `terragrunt_validate` | Validates all [Terragrunt](https://github.com/gruntwork-io/terragrunt) configuration files (`*.hcl`) | `terragrunt` |
230-
| `terrascan` | [terrascan](https://github.com/accurics/terrascan) Detect compliance and security violations. [Hook notes](#terrascan) | `terrascan` |
235+
| `terrascan` | [terrascan](https://github.com/accurics/terrascan) Detect compliance and security violations. [Hook notes](#terrascan) | `terrascan` |
236+
| `tfupdate` | [tfupdate](https://github.com/minamijoyo/tfupdate) Update version constraints of Terraform core, providers, and modules. [Hook notes](#tfupdate) | `tfupdate` |
231237
<!-- markdownlint-enable no-inline-html -->
232238

233239
Check the [source file](https://github.com/antonbabenko/pre-commit-terraform/blob/master/.pre-commit-hooks.yaml) to know arguments used for each hook.
@@ -620,6 +626,33 @@ Example:
620626
3. Use `--skip-rules="ruleID1,ruleID2"` parameter to skip one or more rules globally while scanning (e.g.: `--args=--skip-rules="ruleID1,ruleID2"`).
621627
4. Use the syntax `#ts:skip=RuleID optional_comment` inside a resource to skip the rule for that resource.
622628

629+
### tfupdate
630+
631+
1. Out of the box `tfupdate` will pin the terraform version:
632+
633+
```yaml
634+
- id: tfupdate
635+
name: Autoupdate Terraform versions
636+
```
637+
638+
2. If you'd like to pin providers, etc., use custom arguments, i.e `provider=PROVIDER_NAME`:
639+
640+
```yaml
641+
- id: tfupdate
642+
name: Autoupdate AWS provider versions
643+
args:
644+
- --args=provider aws # Will be pined to latest version
645+
646+
- id: tfupdate
647+
name: Autoupdate Helm provider versions
648+
args:
649+
- --args=provider helm
650+
- --args=--version 2.5.0 # Will be pined to specified version
651+
```
652+
653+
Check [`tfupdate` usage instructions](https://github.com/minamijoyo/tfupdate#usage) for other available options and usage examples.
654+
No need to pass `--recursive .` as it is added automatically.
655+
623656
## Authors
624657

625658
This repository is managed by [Anton Babenko](https://github.com/antonbabenko) with help from these awesome contributors:

hooks/tfupdate.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env bash
2+
set -eo pipefail
3+
4+
# globals variables
5+
# hook ID, see `- id` for details in .pre-commit-hooks.yaml file
6+
readonly HOOK_ID='tfupdate'
7+
# shellcheck disable=SC2155 # No way to assign to readonly variable in separate lines
8+
readonly SCRIPT_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
9+
# shellcheck source=_common.sh
10+
. "$SCRIPT_DIR/_common.sh"
11+
12+
function main {
13+
common::initialize "$SCRIPT_DIR"
14+
common::parse_cmdline "$@"
15+
# shellcheck disable=SC2153 # False positive
16+
common::per_dir_hook "${ARGS[*]}" "$HOOK_ID" "${FILES[@]}"
17+
}
18+
#######################################################################
19+
# Unique part of `common::per_dir_hook`. The function is executed in loop
20+
# on each provided dir path. Run wrapped tool with specified arguments
21+
# Arguments:
22+
# args (string with array) arguments that configure wrapped tool behavior
23+
# dir_path (string) PATH to dir relative to git repo root.
24+
# Can be used in error logging
25+
# Outputs:
26+
# If failed - print out hook checks status
27+
#######################################################################
28+
function per_dir_hook_unique_part {
29+
local -r args="$1"
30+
# shellcheck disable=SC2034 # Unused var.
31+
local -r dir_path="$2"
32+
33+
# pass the arguments to hook
34+
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
35+
tfupdate ${args[@]} "${dir_path}"
36+
37+
# return exit code to common::per_dir_hook
38+
local exit_code=$?
39+
return $exit_code
40+
}
41+
42+
#######################################################################
43+
# Unique part of `common::per_dir_hook`. The function is executed one time
44+
# in the root git repo
45+
# Arguments:
46+
# args (string with array) arguments that configure wrapped tool behavior
47+
#######################################################################
48+
function run_hook_on_whole_repo {
49+
local -r args="$1"
50+
# pass the arguments to hook
51+
# shellcheck disable=SC2068 # hook fails when quoting is used ("$arg[@]")
52+
# shellcheck disable=SC2048 # Use "${array[@]}" (with quotes) to prevent whitespace problems.
53+
# shellcheck disable=SC2086 # Double quote to prevent globbing and word splitting.
54+
tfupdate ${args[*]} --recursive .
55+
56+
# return exit code to common::per_dir_hook
57+
local exit_code=$?
58+
return $exit_code
59+
}
60+
61+
[ "${BASH_SOURCE[0]}" != "$0" ] || main "$@"

0 commit comments

Comments
 (0)