Sort Terraform Variables in Alphabetical Order

Copy of script can be found https://github.com/libre-devops/utils/blob/dev/scripts/terraform/tf-sort.sh

The script takes arguments as inputs, or defaults to reordering a file called input.tf and will sort your terraform variables in alphabetical order

Here is some handy examples below with various use cases:

Using curl with arguments

curl https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- variables.tf sorted-vars.tf

Using wget with default behaviour

wget -O - https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash

Using wget with output.tf instead of input

wget -O - https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- output.tf output.tf

Create Aliases

You can also just make aliases to make this easier

Sort input.tf

echo "alias stfi='curl https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- input.tf input.tf'" >> ~/.bashrc && source ~/.bashrc

Then:

stfi

Sort output.tf

echo "alias stfo='wget -O - https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- output output.tf'" >> ~/.bashrc && source ~/.bashrc

Then:

stfo

Add locally - sudo nano /use/bin/stfi && sudo chmod +X /use/bin/stfi

#!/usr/bin/env bash
# This script will sort your terraform variables in alphabetical order.
# We took the main concept of this script from the author whom is still credited in the heredoc.
#
# RUN AT YOUR OWN PERIL
#
# Master copy at https://github.com/libre-devops/utils/blob/dev/scripts/terraform/tf-sort.sh
#
# This script fis set to take arguments, so you can run it like so from anywhere with bash, curl or wget and awk:
#
# curl https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- input.tf sorted-input.tf
#
# wget -O - https://raw.githubusercontent.com/libre-devops/utils/dev/scripts/terraform/tf-sort.sh | bash -s -- input.tf input.tf
#
#Handy guide over at https://www.libredevops.org/quickstart/utils/scripts/linux/sort-terraform-variables.html

set -euo pipefail

tf_variables_file="${1:-input.tf}"
sorted_tf_variables_file="${2:-input.tf}"

cat <<- 'EOF' > sort-tf.awk
#!/usr/bin/env -S awk -f
# https://gist.github.com/yermulnik/7e0cf991962680d406692e1db1b551e6
# Tested with GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.2.0)
# Usage: cat variables.tf | awk -f /path/to/tf_vars_sort.awk | tee sorted_variables.tf
# No licensing; yermulnik@gmail.com, 2021-2022
# Copied by Libre DevOps on May 2022, master copy stored -
{
	# skip blank lines at the beginning of file
	if (!resource_type && length($0) == 0) next

	# pick only known Terraform resource definition block names of the 1st level
	# https://github.com/hashicorp/terraform/blob/main/internal/configs/parser_config.go#L55-L163
	switch ($0) {
		case /^[[:space:]]*(locals|moved|terraform)[[:space:]]+{/:
			resource_type = $1
			resource_ident = resource_type "|" block_counter++
		case /^[[:space:]]*(data|resource)[[:space:]]+("?[[:alnum:]_-]+"?[[:space:]]+){2}{/:
			resource_type = $1
			resource_subtype = $2
			resource_name = $3
			resource_ident = resource_type "|" resource_subtype "|" resource_name
		case /^[[:space:]]*(module|output|provider|variable)[[:space:]]+"?[[:alnum:]_-]+"?[[:space:]]+{/:
			resource_type = $1
			resource_name = $2
			resource_ident = resource_type "|" resource_name
	}
	arr[resource_ident] = arr[resource_ident] ? arr[resource_ident] RS $0 : $0
} END {
	# exit if there was solely empty input
	# (input consisting of multiple empty lines only, counts in as empty input too)
	if (length(arr) == 0) exit
	# declare empty array (the one to hold final result)
	split("", res)
	# case-insensitive string operations in this block
	# (primarily for the `asort()` call below)
	IGNORECASE = 1
	# sort by `resource_ident` which is a key in our case
	asort(arr)

	# blank-lines-fix each block
	for (item in arr) {
		split(arr[item],new_arr,RS)

		# remove multiple blank lines at the end of resource definition block
		while (length(new_arr[length(new_arr)]) == 0) delete new_arr[length(new_arr)]

		# add one single blank line at the end of the resource definition block
		# so that blocks are delimited with a blank like to align with TF code style
		new_arr[length(new_arr)+1] = RS

		# fill resulting array with data from each resource definition block
		for (line in new_arr) {
			# trim whitespaces at the end of each line in resource definition block
			gsub(/[[:space:]]+$/, "", new_arr[line])
			res[length(res)+1] = new_arr[line]
		}
	}

	# ensure there are no extra blank lines at the beginning and end of data
	while (length(res[1]) == 0) delete res[1]
	while (length(res[length(res)]) == 0) delete res[length(res)]

	# print resulting data to stdout
	for (line in res) {
		print res[line]
	}
}
EOF

# shellcheck disable=SC2002
cat "${tf_variables_file}" | awk -f sort-tf.awk | tee ${sorted_tf_variables_file} && \
rm -rf sort-tf.awk

Then

stfi

Source: docs/quickstart/utils/sort-terraform-variables.md