Created
January 10, 2020 17:27
-
-
Save brodygov/5a77db9474ecdbc633eac65d47e1f3e4 to your computer and use it in GitHub Desktop.
Revisions
-
brodygov created this gist
Jan 10, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,307 @@ #!/bin/bash # Common shell functions. # Having a library like this is a surefire sign that you are using too much # shell and should switch to something like Ruby. But our scripts currently # pass around a ton of stuff with shell environment variables, so this will # have to do for the time being. run() { echo >&2 "+ $*" "$@" } # Prompt the user for a yes/no response. # Exit codes: # 0: user entered yes # 2: STDIN is not a TTY # 10: user entered no # prompt_yn() { local prompt ans if [ $# -ge 1 ]; then prompt="$1" else prompt="Continue?" fi if [ ! -t 0 ]; then echo >&2 "$prompt [y/n]" echo >&2 "prompt_yn: error: stdin is not a TTY!" return 2 fi while true; do read -r -p "$prompt [y/n] " ans case "$ans" in Y|y|yes|YES|Yes) return ;; N|n|no|NO|No) return 10 ;; esac done } # usage: backup_if_exists FILE/DIR MODE # # If FILE/DIR exists, prompt to back it up. # MODE can be --overwrite or --abort. This is used to hint the user for what # will happen upon a "no" answer. # # Upon yes, move it to a timestamped backup name. # Upon no, return 1 if --abort is given, 0 if --abort is given. # backup_if_exists() { local target backup_name overwrite target="$1" mode="$2" case "$mode" in --overwrite) overwrite=1 prompt="Would you like to back it up? Y=backup N=overwrite" ;; --abort) overwrite= prompt="Would you like to back it up? Y=backup N=abort" ;; *) echo_red >&2 "Unexpected backup mode $mode" return 2 ;; esac if [ -e "$target" ]; then echo_yellow >&2 "warning: '$target' already exists" prompt_yn "$prompt" && ret=$? || ret=$? case "$ret" in 0) backup_name="$target.backup~$(date "+%F.%H-%M-%S")" run mv -iv "$target" "$backup_name" ;; 10) if [ -n "$overwrite" ]; then echo_yellow >&2 "OK, not backing up" return else echo_yellow >&2 "OK, returning error $ret" return "$ret" fi ;; *) echo_red >&2 "Unexpected return value $ret from prompt_yn" return "$ret" ;; esac fi } echo_color() { local color code color="$1" shift case "$color" in red) code=31 ;; green) code=32 ;; yellow) code=33 ;; blue) code=34 ;; purple) code=35 ;; cyan) code=36 ;; *) echo >&2 "echo_color: unknown color $color" return 1 ;; esac if [ -t 1 ]; then echo -ne "\\033[1;${code}m" fi echo -n "$*" if [ -t 1 ]; then echo -ne '\033[m' fi echo } echo_blue() { echo_color blue "$@" } echo_green() { echo_color green "$@" } echo_red() { echo_color red "$@" } echo_yellow() { echo_color yellow "$@" } # Print underscores as wide as the terminal screen echo_color_horizontal_rule() { declare -i width # local integer width="${COLUMNS-80}" local color case $# in 0) color=blue ;; 1) color="$1" ;; *) echo >&2 "usage: echo_color_horizontal_rule [COLOR]" return 1 ;; esac echo_color "$color" "$(printf "%0.s_" $(seq 1 "$width"))" } log() { local color= if [ "${1-}" = "--blue" ]; then color=34 shift fi # print our caller if possible as the basename if [ "${#BASH_SOURCE[@]}" -ge 2 ]; then local basename basename="${BASH_SOURCE[1]}" if [[ $basename = */* ]]; then basename="$(basename "$basename")" fi if [ -n "$color" ] && [ -t 2 ]; then echo >&2 -ne "\\033[1;${color}m" fi echo >&2 -n "$basename: " fi echo >&2 -n "$*" if [ -n "$color" ] && [ -t 2 ]; then echo >&2 -ne '\033[m' fi echo >&2 } get_terraform_version() { local output # checkpoint is the hashicorp thing that phones home to check versions output="$(CHECKPOINT_DISABLE=1 run terraform --version)" || return $? # we do this in two phases to avoid sending SIGPIPE to terraform, which # would cause it to exit with status 141 echo "$output" | head -1 | cut -d' ' -f2 } assert_file_not_exists() { if [ -e "$1" ]; then echo_red >&2 "error: \`$1' already exists!" return 1 fi } assert_file_exists() { if [ ! -e "$1" ]; then echo_red >&2 "error: \`$1' does not exist!" return 1 fi } # usage: check_terraform_version SUPPORTED_VERSION... # # e.g. check_terraform_version v0.8.* v0.9.* # # Check whether the current version of terraform (as reported by terraform # --version) is in the allowed list passed as arguments. Return 0 if so, # otherwise return 1. check_terraform_version() { current_tf_version="$(get_terraform_version)" if [ $# -eq 0 ]; then echo_red >&2 \ "error: no supported versions passed to check_terraform_version" return 2 fi for version in "$@"; do # version is expected to be a pattern # shellcheck disable=SC2053 if [[ $current_tf_version == $version ]]; then echo "Terraform version $current_tf_version is supported" return fi done echo_red >&2 "Terraform version $current_tf_version is not supported" echo_red >&2 "Expected versions: $*" echo >&2 "Try using \`bin/terraform-switch.sh\` to install / switch" echo >&2 "to a target installed version of terraform with homebrew." return 1 } # Similar to Ruby's Array#join # usage: join_by DELIMITER ELEM... join_by() { local delimiter="$1" shift if [ $# -eq 0 ]; then echo return fi # print first elem with no delimiter echo -n "$1" shift for elem in "$@"; do echo -n "$delimiter$elem" done echo } # Output shell array as a terraform-compatible string # (1 2 3) => '["1", "2", "3"]' array_to_string() { echo "[\"$(join_by '", "' "$@")\"]" } # Usage: verify_repo_root_unchanged REPO_ROOT_BEFORE_CD BASENAME # # Double check that the repo root has not changed after executing a cd. This is # useful in case you are running a script like tf-deploy or diff-deploy on your # PATH, since the script will cd to the script's own parent directory.. # # If your prior cwd repo root was not the same as the new repo root, this means # that you are probably executing a different script from the one you expected. # Prompt to confirm, since this is probably not what the user intended. # verify_repo_root_unchanged() { local repo_root_before_cd repo_root_after_cd BASENAME repo_root_before_cd="$1" BASENAME="$2" repo_root_after_cd="$(git rev-parse --show-toplevel)" if [ -n "$repo_root_before_cd" ] \ && [ -e "$repo_root_before_cd/bin/$BASENAME" ] \ && [ "$repo_root_before_cd" != "$repo_root_after_cd" ] then echo_yellow >&2 "WARNING: your cwd is in a different directory than $BASENAME. Are you sure you didn't mean to run ./bin/$BASENAME instead? Repo root from your cwd: $repo_root_before_cd Repo root for $BASENAME: $repo_root_after_cd" prompt_yn fi }