1.6.4.1. terrafmt
In large-scale infrastructure automation projects, Terraform configurations often exist not only within .tf files themselves but are also embedded in Markdown documents, test code, template strings, and even Go source code. How can we maintain high quality and consistent code style while ensuring the readability of these embedded HCL snippets? This is precisely the purpose for which terrafmt was created.
terrafmt is a command-line tool designed to extract, format, upgrade, and check Terraform configuration blocks embedded in various types of files. Its goal is similar to terraform fmt, but with a broader scope, supporting the handling of multiple nesting scenarios in both code and documentation.
1.6.4.1.1. Core Features of terrafmt
- Extracting and Formatting Embedded Terraform Blocks
terrafmt automatically recognizes HCL code snippets within the following blocks and formats them:
| start | end |
|---|---|
| ```hcl | ``` |
| ```tf | `, |
| ```terraform | `, |
| return fmt.Sprintf(` | `, |
| return fmt.Sprintf(` | `) |
| return ` | ` |
For example, consider the following Markdown file:
```hcl
resource "aws_instance" "example" {
ami = "ami-2757f631"
instance_type = "t2.micro"
}
```
With terrafmt, this can be automatically formatted into a clearer, properly indented form:
```hcl
resource "aws_instance" "example" {
ami = "ami-2757f631"
instance_type = "t2.micro"
}
```
- Batch Processing and Diff Checking
You can batch format Terraform blocks in all .md files within a directory using the following command:
find . | egrep ".md" | sort | while read f; do terrafmt fmt -f $f; done
You can also use the diff command to preview which parts will be formatted:
terrafmt diff -f README.md
- Rich Output and Integration Options
terrafmt supports outputting extracted code blocks in various formats, such as plain text and JSON, facilitating automation integration and code analysis. Additionally, it returns different exit codes for different outcomes, making it convenient to perform automatic format checks and blocking in CI/CD pipelines.
1.6.4.1.2. Typical Command Usage
- Extract Terraform blocks from a file
terrafmt blocks README.md
- Show only the differences requiring formatting
terrafmt diff -f README.md
- Format and update the file directly
terrafmt fmt -f README.md
- Check format differences and block in CI using exit codes
terrafmt diff --check -f .
1.6.4.1.3. Differences and Advantages Over Traditional terraform fmt
Unlike the official terraform fmt tool, terrafmt is capable of handling embedded configuration blocks in files other than pure .tf files. Whether in Markdown documentation, Provider test code, or template strings, as long as the code block is wrapped in appropriate markers, it can be automatically extracted and standardized. This is crucial for teams that need to uniformly govern a large volume of documentation, tests, and module examples.
Furthermore, terrafmt offers excellent compatibility with Go templates (such as %[1]s), solving the issue where terraform fmt cannot directly process such strings.
1.6.4.1.4. Usage of terrafmt in AVM
AVM uses the following scripts to format HCL code within documentation and potential Terratest code:
echo "==> Fixing test and document terraform blocks code with terrafmt..."
files=$(find . -type f -name "*.md" -o -name "*.go" | grep -v -e ".github" -e "-terraform" -e "vendor" -e ".terraform" -e "README.md" -e "README-generated.md")
for f in $files; do
terrafmt fmt -f "$f"
retValue=$?
if [ $retValue -ne 0 ]; then
echo "------------------------------------------------"
echo ""
echo "The preceding files contain terraform blocks that are not correctly formatted or contain errors."
echo ""
exit $retValue
fi
done
Then, the following script is used to check if changes submitted in a Pull Request have messed up the formatting of HCL code in the documentation:
#!/usr/bin/env bash
echo "==> Checking documentation terraform blocks are formatted..."
files=$(find . -type f -name "*.md" -o -name "*.go" | grep -v -e ".github" -e "-terraform" -e "vendor" -e ".terraform" -e "README.md")
error=false
for f in $files; do
terrafmt diff -c -q "$f"
retValue=$?
if [ $retValue -ne 0 ] && [ $retValue -ne 2 ]; then
error=true
fi
done
if ${error}; then
echo "------------------------------------------------"
echo ""
echo "The preceding files contain terraform blocks that are not correctly formatted or contain errors."
echo "You can fix this by running make tools and then terrafmt on them."
echo ""
echo "to easily fix all terraform blocks:"
echo "$ make terrafmt"
echo ""
exit 1
fi
exit 0