Skip to content

Instantly share code, notes, and snippets.

@maunzCache
Created October 5, 2023 07:37
Show Gist options
  • Save maunzCache/cfa1d015a738afa6b8cd23ef37d77fd0 to your computer and use it in GitHub Desktop.
Save maunzCache/cfa1d015a738afa6b8cd23ef37d77fd0 to your computer and use it in GitHub Desktop.
OpenTofu installer
#!/usr/bin/env bash
set -e
# OPENTOFU INSTALLER based on
# TERRAFORM INSTALLER - Automated Terraform Installation
# Apache 2 License - Copyright (c) 2018 Robert Peteuil @RobertPeteuil
#
# Automatically Download, Extract and Install
# Latest or Specific Version of Terraform
#
# from: https://github.com/robertpeteuil/terraform-installer
# Uncomment line below to always use 'sudo' to install to /usr/local/bin/
# sudoInstall=true
scriptname=$(basename "$0")
scriptbuildnum="2.0.0"
scriptbuilddate="2023-10-05"
# CHECK DEPENDANCIES AND SET NET RETRIEVAL TOOL
if ! unzip -h 2&> /dev/null; then
echo "aborting - unzip not installed and required"
exit 1
fi
if curl -h 2&> /dev/null; then
nettool="curl"
elif wget -h 2&> /dev/null; then
nettool="wget"
else
echo "aborting - wget or curl not installed and required"
exit 1
fi
displayVer() {
echo -e "${scriptname} ver ${scriptbuildnum} - ${scriptbuilddate}"
}
usage() {
[[ "$1" ]] && echo -e "Download and Install OpenTofu - Latest Version unless '-i' specified\n"
echo -e "usage: ${scriptname} [-i VERSION] [-a] [-c] [-h] [-u] [-v]"
echo -e " -i VERSION\t: specify version to install in format '1.6.0-alpha1' (OPTIONAL)"
echo -e " -a\t\t: automatically use sudo to install to /usr/local/bin (or \$TF_INSTALL_DIR)"
echo -e " -c\t\t: leave binary in working directory (for CI/DevOps use)"
echo -e " -h\t\t: help"
echo -e " -u\t\t: allow to auto-pick any unstable version as latest"
echo -e " -v\t\t: display ${scriptname} version"
}
getLatest() {
# USE NET RETRIEVAL TOOL TO GET LATEST VERSION
case "${nettool}" in
# parse version from github API
wget)
LATEST_ARR=($(wget -q -O- https://api.github.com/repos/opentofu/opentofu/releases 2> /dev/null | awk '/tag_name/ {print $2}' | cut -d '"' -f 2 | cut -d 'v' -f 2))
;;
curl)
LATEST_ARR=($(curl -s https://api.github.com/repos/opentofu/opentofu/releases 2> /dev/null | awk '/tag_name/ {print $2}' | cut -d '"' -f 2 | cut -d 'v' -f 2))
;;
*)
echo "Unable to get latest version from Github."
;;
esac
# make sure latest version isn't beta or rc
for ver in "${LATEST_ARR[@]}"; do
if [[ $unstable != "true" ]] && [[ ! $ver =~ beta ]] && [[ ! $ver =~ rc ]] && [[ ! $ver =~ alpha ]]; then
LATEST="$ver"
break
elif [[ $unstable ]]; then
# TODO: If can be shortened
LATEST="$ver"
break
fi
done
echo -n "$LATEST"
}
while getopts ":i:achuv" arg; do
case "${arg}" in
a) sudoInstall=true;;
c) cwdInstall=true;;
i) VERSION=${OPTARG};;
h) usage x; exit;;
u) unstable=true;;
v) displayVer; exit;;
\?) echo -e "Error - Invalid option: $OPTARG"; usage; exit;;
:) echo "Error - $OPTARG requires an argument"; usage; exit 1;;
esac
done
shift $((OPTIND-1))
# POPULATE VARIABLES NEEDED TO CREATE DOWNLOAD URL AND FILENAME
if [[ -z "$VERSION" ]]; then
VERSION=$(getLatest)
fi
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
if [[ "$OS" == "linux" ]]; then
PROC=$(lscpu 2> /dev/null | awk '/Architecture/ {if($2 == "x86_64") {print "amd64"; exit} else if($2 ~ /arm/) {print "arm"; exit} else if($2 ~ /aarch64/) {print "arm"; exit} else {print "386"; exit}}')
if [[ -z $PROC ]]; then
PROC=$(cat /proc/cpuinfo | awk '/model\ name/ {if($0 ~ /ARM/) {print "arm"; exit}}')
fi
if [[ -z $PROC ]]; then
PROC=$(cat /proc/cpuinfo | awk '/flags/ {if($0 ~ /lm/) {print "amd64"; exit} else {print "386"; exit}}')
fi
else
PROC="amd64"
fi
[[ $PROC =~ arm ]] && PROC="arm" # opentofu downloads use "arm" not full arm type
# CREATE FILENAME AND URL FROM GATHERED PARAMETERS
FILENAME="tofu_${VERSION}_${OS}_${PROC}.zip"
LINK="https://github.com/opentofu/opentofu/releases/download/v${VERSION}/${FILENAME}"
SHALINK="https://github.com/opentofu/opentofu/releases/download/v${VERSION}/tofu_${VERSION}_SHA256SUMS"
# TEST CALCULATED LINKS
case "${nettool}" in
wget*)
LINKVALID=$(wget --spider -S "$LINK" 2>&1 | grep "HTTP/" | awk 'END{print $2}')
SHALINKVALID=$(wget --spider -S "$SHALINK" 2>&1 | grep "HTTP/" | awk 'END{print $2}')
;;
curl*)
LINKVALID=$(curl -L -o /dev/null --silent --head --write-out '%{http_code}\n' "$LINK")
SHALINKVALID=$(curl -L -o /dev/null --silent --head --write-out '%{http_code}\n' "$SHALINK")
;;
esac
# VERIFY LINK VALIDITY
if [[ "$LINKVALID" != 200 ]]; then
echo -e "Cannot Install - Download URL Invalid"
echo -e "\nParameters:"
echo -e "\tVER:\t$VERSION"
echo -e "\tOS:\t$OS"
echo -e "\tPROC:\t$PROC"
echo -e "\tURL:\t$LINK"
exit 1
fi
# VERIFY SHA LINK VALIDITY
if [[ "$SHALINKVALID" != 200 ]]; then
echo -e "Cannot Install - URL for Checksum File Invalid"
echo -e "\tURL:\t$SHALINK"
exit 1
fi
# DETERMINE DESTINATION
if [[ "$cwdInstall" ]]; then
BINDIR=$(pwd)
elif [[ -n "$TF_INSTALL_DIR" ]]; then
BINDIR="$TF_INSTALL_DIR"
CMDPREFIX="${sudoInstall:+sudo }"
STREAMLINED=true
elif [[ -w "/usr/local/bin" ]]; then
BINDIR="/usr/local/bin"
CMDPREFIX=""
STREAMLINED=true
elif [[ "$sudoInstall" ]]; then
BINDIR="/usr/local/bin"
CMDPREFIX="sudo "
STREAMLINED=true
else
echo -e "OpenTofu Installer\n"
echo "Specify install directory (a,b or c):"
echo -en "\t(a) '~/bin' (b) '/usr/local/bin' as root (c) abort : "
read -r -n 1 SELECTION
echo
if [ "${SELECTION}" == "a" ] || [ "${SELECTION}" == "A" ]; then
BINDIR="${HOME}/bin"
CMDPREFIX=""
elif [ "${SELECTION}" == "b" ] || [ "${SELECTION}" == "B" ]; then
BINDIR="/usr/local/bin"
CMDPREFIX="sudo "
else
exit 0
fi
fi
# CREATE TMPDIR FOR EXTRACTION
if [[ ! "$cwdInstall" ]]; then
TMPDIR=${TMPDIR:-/tmp}
UTILTMPDIR="tofu_${VERSION}"
cd "$TMPDIR" || exit 1
mkdir -p "$UTILTMPDIR"
cd "$UTILTMPDIR" || exit 1
fi
# DOWNLOAD ZIP AND CHECKSUM FILES
case "${nettool}" in
wget*)
wget -q "$LINK" -O "$FILENAME"
wget -q "$SHALINK" -O SHAFILE
;;
curl*)
curl -L -s -o "$FILENAME" "$LINK"
curl -L -s -o SHAFILE "$SHALINK"
;;
esac
# VERIFY ZIP CHECKSUM
if shasum -h 2&> /dev/null; then
expected_sha=$(cat SHAFILE | grep "$FILENAME" | awk '{print $1}')
download_sha=$(shasum -a 256 "$FILENAME" | cut -d' ' -f1)
if [ $expected_sha != $download_sha ]; then
echo "Download Checksum Incorrect"
echo "Expected: $expected_sha"
echo "Actual: $download_sha"
exit 1
fi
fi
# EXTRACT ZIP
unzip -qq "$FILENAME" || exit 1
# COPY TO DESTINATION
if [[ ! "$cwdInstall" ]]; then
mkdir -p "${BINDIR}" || exit 1
${CMDPREFIX} mv tofu "$BINDIR" || exit 1
# CLEANUP AND EXIT
cd "${TMPDIR}" || exit 1
rm -rf "${UTILTMPDIR}"
[[ ! "$STREAMLINED" ]] && echo
echo "OpenTofu Version ${VERSION} installed to ${BINDIR}"
else
rm -f "$FILENAME" SHAFILE
echo "OpenTofu Version ${VERSION} downloaded"
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment