Skip to content

Instantly share code, notes, and snippets.

@omkensey
Last active October 8, 2022 07:07
Show Gist options
  • Save omkensey/244c9a33e89d438f7741606e3434b394 to your computer and use it in GitHub Desktop.
Save omkensey/244c9a33e89d438f7741606e3434b394 to your computer and use it in GitHub Desktop.
#!/bin/bash
PROVIDERS_DEFAULT="aws,awscc,google,azurerm,azuread"
PROVIDERS=""
SEARCH_LOC_DEFAULT=$HOME
SEARCH_LOC=""
TF_BIN=""
STATE_FILE_NAME="terraform.tfstate"
search_states() {
if [ -z $SEARCH_LOC ]; then
echo "Error: search location cannot be an empty string." >&2
exit 1
fi
if ! [ -e "$SEARCH_LOC" ]; then
echo "Error: search location does not exist." >&2
exit 1
fi
if [ -z $PROVIDERS ]; then
echo "Error: provider list cannot be an empty string." >&2
exit 1
fi
if ! command -v jq 2>&1 >/dev/null && [ -z $QUIET_MODE ]; then
echo "Warning: jq not found, falling back to grep (may be less precise)" >&2
fi
provider_arr=(${PROVIDERS//,/ })
provider_num=${#provider_list[@]}
for provider in ${provider_arr[@]}; do
if [ -z $first_provider ]; then
PROVIDER_REGEX="^${provider}_"
first_provider="false"
else
PROVIDER_REGEX="$PROVIDER_REGEX|^${provider}_"
fi
done
STATE_LIST=$(find $SEARCH_LOC -name $STATE_FILE_NAME -type f 2>/dev/null)
for statefile in $STATE_LIST; do
if command -v jq 2>&1 >/dev/null; then
if ! [ -z $FIND_DATA_RESOURCES ]; then
result=$(jq -r '.resources[]|select((.mode == "managed") or (.mode == "data")).type' < $statefile 2>/dev/null | grep -E $PROVIDER_REGEX)
else
result=$(jq -r '.resources[]|select(.mode == "managed").type' < $statefile 2>/dev/null | grep -E $PROVIDER_REGEX)
fi
if ! [ -z "$result" ]; then
echo "${statefile}:"
echo "$result" | sort -u
fi
else
if ! [ -z $FIND_DATA_RESOURCES ]; then
result=$(grep -A 1 -E '^[[:blank:]]*"mode": "managed"|^[[:blank:]]*"mode": "data"' $statefile | grep -E '^[[:blank:]]*"type": ' | cut -d: -f2 | tr -d '," ' | grep -E $PROVIDER_REGEX)
else
result=$(grep -A 1 -E '^[[:blank:]]*"mode": "managed"' $statefile | grep -E '^[[:blank:]]*"type":' | cut -d: -f2 | tr -d '," ' | grep -E $PROVIDER_REGEX)
fi
if ! [ -z "$result" ]; then
echo "${statefile}:"
echo "$result" | sort -u
fi
fi
done
}
output_usage() {
if ! command -v jq 2>&1 >/dev/null && [ -z $QUIET_MODE ]; then
echo "Warning: jq not found. Cannot report Terraform version or reliably \
parse tfstate files without jq." >&2
TF_VERSION="unknown"
else
TF_VERSION=$($TF_BIN version -json | jq -r .terraform_version)
fi
usage_text="Provider search list: ${PROVIDERS}
Location to search for state files: ${SEARCH_LOC}
Current Terraform version: ${TF_VERSION}
Usage: $(basename $0) [options] [arguments]
-a, --all: Find data sources as well as managed resources.
-d, --search-dir: search the specified path (usually a directory but a
single file will work as well).
Defaults to the user's home directory.
-p, --providers: specifies the provider(s) to search for resources created
by. Multiple providers can be specified as a comma-separated list
without spaces.
Defaults to ${PROVIDERS_DEFAULT}.
-t, --tf-bin: Use a specific Terraform binary at [path]. If the given path
is not a valid executable file, a fatal error results.
By default the desired Terraform binary is assumed to be the first one in
the user's path; if there isn't one or you don't want to use that one,
you must use this option.
-q, --quiet: Suppress non-fatal warning output.
-h, --help: Display this usage info."
OUTPUT_FD="${1-"1"}"
echo "$usage_text" >&${OUTPUT_FD}
}
#optspec=":a:o:ev:h-:"
optspec=":ad:p:t:qh-:"
while getopts "$optspec" optchar; do
case "${optchar}" in
-)
case "${OPTARG}" in
all)
FIND_DATA_RESOURCES="true"
;;
providers)
PROVIDERS="${!OPTIND@L}"; OPTIND=$(( $OPTIND + 1 ))
;;
search-dir)
SEARCH_LOC="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
;;
tf-bin)
TF_BIN="${!OPTIND}"; OPTIND=$(( $OPTIND + 1 ))
;;
quiet)
QUIET_MODE="1"
;;
help)
OUTPUT_USAGE="true"
;;
*)
if [ "$OPTERR" = 1 ] && [ "${optspec:0:1}" != ":" ]; then
echo "Unknown option --${OPTARG}" >&2
echo "" >&2
OUTPUT_USAGE_ERR="true"
fi
;;
esac
;;
a)
FIND_DATA_RESOURCES="true"
;;
d)
SEARCH_LOC="${OPTARG}"
;;
p)
PROVIDERS="${OPTARG@L}"
;;
t)
TF_BIN="${OPTARG}"
;;
q)
QUIET_MODE="1"
;;
h)
OUTPUT_USAGE="true"
;;
*)
if [ "$OPTERR" != 1 ] || [ "${optspec:0:1}" = ":" ]; then
echo "Unknown option -${optchar}" >&2
echo "" >&2
OUTPUT_USAGE_ERR="true"
fi
;;
esac
done
shift $((OPTIND-1))
if ! [ -z $TF_BIN ] && ! command -v "$TF_BIN" 2>&1 > /dev/null; then
echo "Terraform not found or not executable at the specified path." >&2
exit 1
elif ! command -v terraform 2>&1 > /dev/null; then
echo "No Terraform executable found. Install Terraform in your execution \
path or use -t/--tf-bin to point to its location."
else
TF_BIN=${TF_BIN:-"terraform"}
fi
PROVIDERS=${PROVIDERS:-$PROVIDERS_DEFAULT}
SEARCH_LOC=${SEARCH_LOC:-$SEARCH_LOC_DEFAULT}
if ! [ -z $OUTPUT_USAGE_ERR ]; then
output_usage 2
exit 1
fi
if ! [ -z $OUTPUT_USAGE ]; then
output_usage
exit 0
fi
search_states
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment