Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ jobs:
strategy:
matrix:
os:
- 'macos-11'
- 'macos-latest'
- 'ubuntu-latest'
steps:
- uses: 'actions/checkout@v2'
with:
fetch-depth: 1
- name: 'Install Dependencies'
run: './test/install_deps.sh'
- name: 'Run all tests'
run: './test/run.sh'
shell: 'bash'
Expand All @@ -41,6 +44,10 @@ jobs:
- 'windows-2019'
steps:
- uses: 'actions/checkout@v2'
with:
fetch-depth: 1
- name: 'Install Dependencies'
run: './test/install_deps.sh'
- name: 'Run all tests'
run: './test/run.sh'
shell: 'bash'
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ $ which tfenv

Install a specific version of Terraform.

If no parameter is passed, the version to use is resolved automatically via [.terraform-version files](#terraform-version-file) or [TFENV\_TERRAFORM\_VERSION environment variable](#tfenv_terraform_version) (TFENV\_TERRAFORM\_VERSION takes precedence), defaulting to 'latest' if none are found.
If no parameter is passed, the version to use is resolved automatically via [TFENV\_TERRAFORM\_VERSION environment variable](#tfenv_terraform_version), [.terraform-version files](#terraform-version-file), or [required_version in "terraform" section of any .tf or .tf.json file](#min-required), in that order of precedence, i.e. TFENV\_TERRAFORM\_VERSION, then .terraform-version, and then required_version in .tf. The default is 'latest' if none are found.

If a parameter is passed, available options:

Expand Down
6 changes: 3 additions & 3 deletions bin/terraform
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ if [ -z "${TFENV_ROOT:-""}" ]; then
};
TFENV_SHIM=$(readlink_f "${0}")
TFENV_ROOT="${TFENV_SHIM%/*/*}";
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT"
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT";
else
TFENV_ROOT="${TFENV_ROOT%/}";
fi;
Expand All @@ -47,7 +47,7 @@ fi;
for dir in libexec bin; do
case ":${PATH}:" in
*:${TFENV_ROOT}/${dir}:*) log 'debug' "\$PATH already contains '${TFENV_ROOT}/${dir}', not adding it again";;
*)
*)
log 'debug' "\$PATH does not contain '${TFENV_ROOT}/${dir}', prepending and exporting it now";
export PATH="${TFENV_ROOT}/${dir}:${PATH}";
;;
Expand All @@ -62,4 +62,4 @@ log 'debug' "program=\"${0##*/}\"";

declare tfenv_path="${TFENV_ROOT}/bin/tfenv";

tfenv-exec "$@"
tfenv-exec "$@";
6 changes: 3 additions & 3 deletions bin/tfenv
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ if [ -z "${TFENV_ROOT:-""}" ]; then
};
TFENV_SHIM=$(readlink_f "${0}")
TFENV_ROOT="${TFENV_SHIM%/*/*}";
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT"
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT";

else
TFENV_ROOT="${TFENV_ROOT%/}";
Expand All @@ -48,7 +48,7 @@ fi;
for dir in libexec bin; do
case ":${PATH}:" in
*:${TFENV_ROOT}/${dir}:*) log 'debug' "\$PATH already contains '${TFENV_ROOT}/${dir}', not adding it again";;
*)
*)
log 'debug' "\$PATH does not contain '${TFENV_ROOT}/${dir}', prepending and exporting it now";
export PATH="${TFENV_ROOT}/${dir}:${PATH}";
;;
Expand All @@ -62,7 +62,7 @@ done;
declare arg="${1:-""}";

log 'debug' "Setting TFENV_DIR to ${PWD}";
export TFENV_DIR="${PWD}"
export TFENV_DIR="${PWD}";

abort() {
log 'debug' 'Aborting...';
Expand Down
6 changes: 3 additions & 3 deletions lib/bashlog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ function log() {
local severities_ALERT=1; # Unused
local severities_EMERG=0; # Unused

local severity_var="severities_${upper}"
local severity="${!severity_var:-3}"
local severity_var="severities_${upper}";
local severity="${!severity_var:-3}";

if [ "${debug_level}" -gt 0 ] || [ "${severity}" -lt 7 ]; then

Expand Down Expand Up @@ -111,7 +111,7 @@ function log() {
local colours_DEFAULT='\033[0m' # Default

local norm="${colours_DEFAULT}";
local colour_var="colours_${upper}"
local colour_var="colours_${upper}";
local colour="${!colour_var:-\033[31m}";

local std_line;
Expand Down
65 changes: 51 additions & 14 deletions lib/helpers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ if [ -z "${TFENV_ROOT:-""}" ]; then
};
TFENV_SHIM=$(readlink_f "${0}")
TFENV_ROOT="${TFENV_SHIM%/*/*}";
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT"
[ -n "${TFENV_ROOT}" ] || early_death "Failed to determine TFENV_ROOT";
else
TFENV_ROOT="${TFENV_ROOT%/}";
fi;
Expand All @@ -44,23 +44,24 @@ fi;

function load_bashlog () {
source "${TFENV_ROOT}/lib/bashlog.sh";
}
};
export -f load_bashlog;

if [ "${TFENV_DEBUG:-0}" -gt 0 ] ; then
# our shim below cannot be used when debugging is enabled
load_bashlog
load_bashlog;
else
# Shim that understands to no-op for debug messages, and defers to
# full bashlog for everything else.
function log () {
if [ "$1" != 'debug' ] ; then
# Loading full bashlog will overwrite the `log` function
load_bashlog
log "$@"
fi
}
load_bashlog;
log "$@";
fi;
};
export -f log;
fi
fi;

resolve_version () {
declare version_requested version regex min_required version_file;
Expand All @@ -75,19 +76,41 @@ resolve_version () {
log 'debug' "Version File (${version_file}) is not the default \${TFENV_CONFIG_DIR}/version (${TFENV_CONFIG_DIR}/version)";
version_requested="$(cat "${version_file}")" \
|| log 'error' "Failed to open ${version_file}";
fi

elif [ -f "${version_file}" ]; then
if [ -z "${version_requested:-""}" ]; then
log 'debug' 'Trying to set version from "required_version" under "terraform" section';
versions="$( echo $(cat {*.tf,*.tf.json} 2>/dev/null | grep -h required_version) | grep -o '\([0-9]\+\.\?\)\{2,3\}\(-[a-z]\+[0-9]\+\)\?')";
if [[ "${versions}" =~ ([~=!<>]{0,2}[[:blank:]]*[0-9]+[0-9.]+)[^0-9]*(-[a-z]+[0-9]+)? ]]; then
found_min_required="${BASH_REMATCH[1]}${BASH_REMATCH[2]}";
if [[ "${found_min_required}" =~ ^!=.+ ]]; then
log 'debug' "required_version is a negation - we cannot guess the desired one, skipping.";
else
found_min_required="$(echo "$found_min_required")";

# Probably not an advisable way to choose a terraform version,
# but this is the way this functionality works in terraform:
# add .0 to versions without a minor and/or patch version (e.g. 12.0)
while ! [[ "${found_min_required}" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; do
found_min_required="${found_min_required}.0";
done;
version_requested="${found_min_required}";
fi;
fi;
fi;

if [ -z "${version_requested}" -a -f "${version_file}" ]; then
log 'debug' "Version File is the default \${TFENV_CONFIG_DIR}/version (${TFENV_CONFIG_DIR}/version)";
version_requested="$(cat "${version_file}")" \
|| log 'error' "Failed to open ${version_file}";

# Absolute fallback
if [ -z "${version_requested}" ]; then
log 'debug' 'Version file had no content. Falling back to "latest"';
version_requested='latest';
fi;

else
# Absolute fallback
elif [ -z "${version_requested}" ]; then
log 'debug' "Version File is the default \${TFENV_CONFIG_DIR}/version (${TFENV_CONFIG_DIR}/version) but it doesn't exist";
log 'info' 'No version requested on the command line or in the version file search path. Installing "latest"';
version_requested='latest';
Expand Down Expand Up @@ -123,7 +146,7 @@ resolve_version () {
regex="^${version_requested}$";
log 'debug' "Version is explicit: ${version}. Regex enforces the version: ${regex}";
fi;
}
};

# Curl wrapper to switch TLS option for each OS
function curlw () {
Expand All @@ -141,13 +164,13 @@ function curlw () {
fi;

curl ${TLS_OPT} ${NETRC_OPT} "$@";
}
};
export -f curlw;

check_active_version() {
local v="${1}";
[ -n "$(${TFENV_ROOT}/bin/terraform version | grep -E "^Terraform v${v}((-dev)|( \([a-f0-9]+\)))?$")" ];
}
};
export -f check_active_version;

check_installed_version() {
Expand All @@ -173,6 +196,8 @@ cleanup() {
rm -rf ./.terraform-version;
log 'debug' "Deleting ${pwd}/min_required.tf";
rm -rf ./min_required.tf;
log 'debug' "Deleting ${pwd}/required_version.tf";
rm -rf ./required_version.tf;
};
export -f cleanup;

Expand All @@ -182,6 +207,18 @@ function error_and_proceed() {
};
export -f error_and_proceed;

function check_dependencies() {
if [[ $(uname) == 'Darwin' ]] && [ $(which brew) ]; then
if ! [ $(which ggrep) ]; then
log 'error' 'A metaphysical dichotomy has caused this unit to overload and shut down. GNU Grep is a requirement and your Mac does not have it. Consider "brew install grep"';
fi;

shopt -s expand_aliases;
alias grep=ggrep;
fi;
};
export -f check_dependencies;

source "$TFENV_ROOT/lib/tfenv-exec.sh";
source "$TFENV_ROOT/lib/tfenv-version-file.sh";
source "$TFENV_ROOT/lib/tfenv-version-name.sh";
Expand Down
2 changes: 1 addition & 1 deletion lib/tfenv-exec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,5 @@ function tfenv-exec() {
|| log 'error' "Failed to execute: ${TF_BIN_PATH} $*";

return 0;
}
};
export -f tfenv-exec;
4 changes: 2 additions & 2 deletions lib/tfenv-version-file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ find_local_version_file() {
done;
log 'debug' "No version file found in ${1}";
return 1;
}
};
export -f find_local_version_file;

function tfenv-version-file() {
Expand All @@ -24,5 +24,5 @@ function tfenv-version-file() {
echo "${TFENV_CONFIG_DIR}/version";
fi;
fi;
}
};
export -f tfenv-version-file;
37 changes: 32 additions & 5 deletions lib/tfenv-version-name.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,36 @@ function tfenv-version-name() {
&& log 'debug' "TFENV_VERSION_FILE retrieved from tfenv-version-file: ${TFENV_VERSION_FILE}" \
|| log 'error' 'Failed to retrieve TFENV_VERSION_FILE from tfenv-version-file';

TFENV_VERSION="$(cat "${TFENV_VERSION_FILE}" || true)" \
&& log 'debug' "TFENV_VERSION specified in TFENV_VERSION_FILE: ${TFENV_VERSION}";
if [ "${TFENV_VERSION_FILE}" = "${TFENV_CONFIG_DIR}/version" ]; then
log 'debug' 'Tryng to set version from "required_version" under "terraform" section';

TFENV_VERSION_SOURCE="${TFENV_VERSION_FILE}";
versions="$( echo $(cat {*.tf,*.tf.json} 2>/dev/null | grep -h required_version) | grep -o '\([0-9]\+\.\?\)\{2,3\}\(-[a-z]\+[0-9]\+\)\?')";
if [[ "${versions}" =~ ([~=!<>]{0,2}[[:blank:]]*[0-9]+[0-9.]+)[^0-9]*(-[a-z]+[0-9]+)? ]]; then
found_min_required="${BASH_REMATCH[1]}${BASH_REMATCH[2]}";
if [[ "${found_min_required}" =~ ^!=.+ ]]; then
log 'debug' "required_version is a negation - we cannot guess the desired one, skipping.";
else
found_min_required="$(echo "$found_min_required")";

# Probably not an advisable way to choose a terraform version,
# but this is the way this functionality works in terraform:
# add .0 to versions without a minor and/or patch version (e.g. 12.0)
while ! [[ "${found_min_required}" =~ [0-9]+\.[0-9]+\.[0-9]+ ]]; do
found_min_required="${found_min_required}.0";
done;
TFENV_VERSION="${found_min_required}";
fi;
fi;

TFENV_VERSION_SOURCE='terraform{required_version}';
fi;

if [[ -z "${TFENV_VERSION:-""}" ]]; then
TFENV_VERSION="$(cat "${TFENV_VERSION_FILE}" || true)" \
&& log 'debug' "TFENV_VERSION specified in TFENV_VERSION_FILE: ${TFENV_VERSION}";

TFENV_VERSION_SOURCE="${TFENV_VERSION_FILE}";
fi;
else
TFENV_VERSION="${TFENV_TERRAFORM_VERSION}" \
&& log 'debug' "TFENV_VERSION specified in TFENV_TERRAFORM_VERSION: ${TFENV_VERSION}";
Expand Down Expand Up @@ -63,7 +89,7 @@ function tfenv-version-name() {

# Accept a v-prefixed version, but strip the v.
if [[ "${TFENV_VERSION}" =~ ^v.*$ ]]; then
log 'debug' "Version Requested is prefixed with a v. Stripping the v."
log 'debug' "Version Requested is prefixed with a v. Stripping the v.";
TFENV_VERSION="${TFENV_VERSION#v*}";
fi;
fi;
Expand All @@ -77,5 +103,6 @@ function tfenv-version-name() {
fi;

echo "${TFENV_VERSION}";
}
};
export -f tfenv-version-name;

2 changes: 1 addition & 1 deletion libexec/tfenv---version
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fi;
for dir in libexec bin; do
case ":${PATH}:" in
*:${TFENV_ROOT}/${dir}:*) log 'debug' "\$PATH already contains '${TFENV_ROOT}/${dir}', not adding it again";;
*)
*)
log 'debug' "\$PATH does not contain '${TFENV_ROOT}/${dir}', prepending and exporting it now";
export PATH="${TFENV_ROOT}/${dir}:${PATH}";
;;
Expand Down
4 changes: 2 additions & 2 deletions libexec/tfenv-exec
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ fi;
for dir in libexec bin; do
case ":${PATH}:" in
*:${TFENV_ROOT}/${dir}:*) log 'debug' "\$PATH already contains '${TFENV_ROOT}/${dir}', not adding it again";;
*)
*)
log 'debug' "\$PATH does not contain '${TFENV_ROOT}/${dir}', prepending and exporting it now";
export PATH="${TFENV_ROOT}/${dir}:${PATH}";
;;
Expand All @@ -72,4 +72,4 @@ done;
# Begin Script Body #
#####################

tfenv-exec "$@"
tfenv-exec "$@";
4 changes: 2 additions & 2 deletions libexec/tfenv-init
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash

[ -n "${TFENV_DEBUG}" ] && set -x
[ -n "${TFENV_DEBUG}" ] && set -x:

export PATH="${TFENV_ROOT}/bin:${PATH}"
export PATH="${TFENV_ROOT}/bin:${PATH}";
Loading