-
-
Save yermulnik/7e0cf991962680d406692e1db1b551e6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env -S awk -f | |
# https://gist.github.com/yermulnik/7e0cf991962680d406692e1db1b551e6 | |
# Tested with GNU Awk 5.1.0, API: 3.0 (GNU MPFR 4.1.0, GNU MP 6.2.1) | |
# Usage: /path/to/tf_vars_sort.awk < variables.tf | tee sorted_variables.tf | |
# Note: "chmod +x /path/to/tf_vars_sort.awk" before use | |
# No licensing; [email protected], 2021-2024 | |
{ | |
# skip blank lines at the beginning of file | |
if (!resource_type && length($0) == 0) next | |
# pick only known Terraform resource definition block types of the 1st level | |
# https://github.com/hashicorp/terraform/blob/main/internal/configs/parser_config.go#L92-L230 | |
switch ($0) { | |
# ex: block_type { | |
case /^[[:space:]]*(import|locals|moved|removed|terraform)[[:space:]]+{/: | |
resource_type = $1 | |
resource_ident = resource_type "|" block_counter++ | |
break | |
# ex: block_type type_label name_label { | |
case /^[[:space:]]*(data|ephemeral|resource)[[:space:]]+("?[[:alnum:]_-]+"?[[:space:]]+){2}{/: | |
resource_type = $1 | |
resource_subtype = $2 | |
resource_name = $3 | |
resource_ident = resource_type "|" resource_subtype "|" resource_name | |
break | |
# ex: block_type name_label { | |
case /^[[:space:]]*(check|module|output|provider|variable)[[:space:]]+"?[[:alnum:]_-]+"?[[:space:]]+{/: | |
resource_type = $1 | |
resource_name = $2 | |
resource_ident = resource_type "|" resource_name | |
break | |
} | |
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] | |
} | |
} |
tfsort
utility released, which provides the alike functionality
@yermulnik This awk script supports more than variables.tf
and output.tf
. I've been unable to use tfsort
for regular resource files whereas this works for a greater context.
@yermulnik This awk script supports more than
variables.tf
andoutput.tf
. I've been unable to usetfsort
for regular resource files whereas this works for a greater context.
@camilosantana Glad to hear this script makes value 👍
Still works, macos Sonoma 14.2.1, GNU Awk 5.3.0, API 4.0, (GNU MPFR 4.2.1, GNU MP 6.3.0), just needed to change awk to 'gawk' in the first line of the script. https://formulae.brew.sh/formula/gawk
#!/usr/bin/env -S gawk -f
...
Wasn't working for "resource" blocks. Until I added break statements to the end of each case! https://www.gnu.org/software/gawk/manual/gawk.html#Break-Statement
Wasn't working for "resource" blocks. Until I added break statements to the end of each case!
@perkerk Thanks for pointing this out.
I've just updated this gist with break
in each case
statement.
And also added more 1st-level block types.
JFYI: recently there was
tfsort
utility released, which provides the alike functionality, but is written in Golang — https://github.com/AlexNabokikh/tfsort