A top-tip for creating new Terraform "tfvars" variables files, ... SergejAlikov wrote a rather nice and simple bit of Golang that supports parsing of v0.11 and v0.12 Terraform HCL files, and outputs a nice JSON structure of inputs, outputs and locals. https://github.com/GeoSpock/tf-named-vals The upshot being you can do things like this:
tf-named-vals a <(cat *.tf) | jq -erf <(cat <<-'EOF'
.variables|to_entries[]|
([.value.type]|flatten) as $types|
($types|join(",")) as $type|
(if ([.value.type]|flatten|contains(["list"])) or (.value.default == null) then "" else "\"" end) as $defquot|
(if .value.default == null then "" else "#" end) as $defcomment|
(if .value.default == null then "" else .value.default end) as $val|
(if .value.description == null then "No description available." else .value.description end) as $desc|
[
"# \($desc) (\($type))",
"\($defcomment)\(.key) = \($defquot)\($val)\($defquot)\n"
] | join("\n")
EOF
)
A more helpful generic version using tooling directly from HashiCorp is as follows:
#!/usr/bin/env bash
# Requires:
# https://www.gnu.org/software/bash/
# https://stedolan.github.io/jq/
# https://github.com/tmccombs/hcl2json
# https://github.com/hashicorp/terraform-config-inspect
# https://www.terraform.io/
set -Eeuo pipefail
# shellcheck disable=SC2154
trap 'declare rc=$?;
>&2 echo "Unexpected error (exit-code $rc) executing $BASH_COMMAND at ${BASH_SOURCE[0]} line $LINENO";
exit $rc' ERR
read_tfvars_as_json () {
declare file="${1:-}"
if [[ -e "$file" && ! -d "$file" && -r "$file" ]] ; then
hcl2json < "${1:-}"
elif [[ ! -t 0 ]] ; then
hcl2json < /dev/stdin
else
echo '{}'
fi
}
merge_tfvars () {
printf '# Generated by "%s%s" command at %s.\n\n' \
"${0##.*/}" "${1:+ }${1:-}" "$(date -R)"
jq -serf <(cat <<-'EOF'
(.[0].variables) as $tf_inspect |
($tf_inspect|map({(.name): .default})|add) as $tf_defaults |
(.[1]) as $tfvars |
($tf_defaults * $tfvars) | to_entries[] |
(.key) as $key |
($tf_inspect[$key]) as $config |
($config.default) as $default |
([$config.type]|flatten|join(",")|gsub("[[:space:]]+";" ")) as $type |
(if $type == "" then "**unknown**" else $type end) as $type |
(if ((.value == $default) and (.value != null)) then "#" else "" end) as $as_comment |
(if $config.description == null then "No description available." else $config.description end) as $description |
[
"# \($description) (\($type))",
"# Default: \($default|@json)",
"\($as_comment)\(.key) = \(if .value == null then "" else .value|@json end)\n"
] | join("\n")
EOF
) \
<(terraform-config-inspect --json) \
<(read_tfvars_as_json "${1:-}")
}
main () {
if ! compgen -G "*.tf" > /dev/null ; then
>&2 echo "No Terraform module(s) detected."
exit 1
fi
declare rendered_tfvars=""
rendered_tfvars="$(merge_tfvars "$@")"
declare reformatted_tfvars=""
if ! reformatted_tfvars="$(terraform fmt - <<< "$rendered_tfvars" 2>/dev/null)" ; then
reformatted_tfvars="$rendered_tfvars"
fi
if [[ -n "${1:-}" ]] ; then
echo "$reformatted_tfvars" > "${1:-}"
if [[ -t 0 ]] && [[ -n "${EDITOR:-}" ]] ; then
exec "$EDITOR" "${1:-}"
fi
else
echo "$reformatted_tfvars"
fi
}
main "$@"