Created
May 6, 2020 10:07
-
-
Save mdtanrikulu/a4bb8975dc3a5e99ac96d8bcbe827eb1 to your computer and use it in GitHub Desktop.
Golem installation script for ElementaryOS
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 characters
#!/bin/bash | |
trap "exit" INT | |
# Meta information | |
SCRIPT_VERSION="0.1.0" | |
SCRIPT_AUTHOR="Karol Tomala" | |
# Default variables | |
DEBUG=0 | |
DOWNLOAD_PROGRESS=0 | |
CLEANUP_TMP=1 | |
INSTALL_DEVELOP=0 | |
INSTALL_OPTIONAL=0 | |
NO_EXTENSIONS_INSTALL=0 | |
EXTENSION_HASH_CHECK=1 | |
EXTRA_PACKAGES=() | |
REMOVE_EXTRA_PACKAGES=() | |
HOLD_PACKAGES=() | |
UNHOLD_PACKAGES=() | |
AFTER_DEPENDENCY_INSTALL_FUNCTIONS=() | |
DOWNLOADERS=( curl wget ) | |
DOWNLOAD_TMP_PATH=/tmp | |
MANIFEST_URL='https://golem-releases.cdn.golem.network/manifest.yml' | |
MANIFEST_FILE='golem_releases_manifest.yml' | |
SUPPORTED_OS=( linux ) | |
MANIFEST_RELEASES_PREFIX="golem_releases" | |
MANIFEST_RELEASES_LATEST="${MANIFEST_RELEASES_PREFIX}_latest" | |
MANIFEST_RELEASES_PUBLISHED="${MANIFEST_RELEASES_PREFIX}_published" | |
MANIFEST_RELEASES_DESCRIPTIONS="${MANIFEST_RELEASES_PREFIX}_descriptions" | |
INSTALL_DESTINATION_PREFIX=/opt/golem | |
INSTALL_SYMLINK_PREFIX=/usr/local/bin | |
TMP_ERR_LOG=/tmp/golem_install_script.err.log | |
SKIP_DEPS_UPDATE=0 | |
OVERWRITE=1 | |
TYPEPRINT_DELAY=.005 | |
DEFAULT_COMPONENT_STATUS="mandatory" | |
# Docker variables | |
DOCKER_GPG_KEY="https://download.docker.com/linux/ubuntu/gpg" | |
DOCKER_VERSION= | |
INSTALL_DOCKER=1 | |
REMOVE_DOCKER=0 | |
DOCKER_CONFIG_FILE="/etc/docker/daemon.json" | |
# Character maps | |
CHAR_UNICODE_SPIN='⡄⡆⡇⠇⠃⠋⠉⠙⠘⠚⠒⠖⠆⠦⠤⢤⢠⣠⣀⣄' | |
CHAR_ASCII_SPIN='-\|/' | |
# Message functions | |
err_msg () { local arg_msg=$*; echo "ERROR: $arg_msg" >&2; exit 1; } | |
warn_msg () { local arg_msg=$*; echo "WARNING: $arg_msg" >&2; } | |
debug_msg () { local arg_msg=$*; [ $DEBUG -eq 1 ] && echo "DEBUG: $arg_msg" >&2; } | |
info_msg () { local arg_msg=$*; echo "$arg_msg"; } | |
spinner_msg () { | |
local arg_msg=$* | |
if [ "$UNICODE_SUPPORT" == "Y" ]; then | |
local bullet="⬝" | |
local tick="✓" | |
local cross="✕" | |
else | |
local bullet="*" | |
local tick="+" | |
local cross="-" | |
fi | |
printf " $bullet $arg_msg " | |
spinner | |
[ $PID_STATUS -eq 0 ] && printf "$tick\n" || printf "$cross\n" | |
return $PID_STATUS | |
} | |
typeprint () { | |
local x=$@ | |
for((i=0;i<${#x};i++));do echo -n "${x:$i:1}";sleep $TYPEPRINT_DELAY;done;echo | |
} | |
# Info functions | |
print_banner () { | |
typeprint "Golem Linux Installer version $SCRIPT_VERSION" | |
} | |
# Helper functions | |
test_unicode () { | |
echo -ne "\xe2\x88\xb4\033[6n\033[1K\r" | |
read -d R foo | |
echo -ne "\033[1K\r" | |
echo -e "${foo}" | cut -d \[ -f 2 | cut -d";" -f 2 | ( | |
read UNICODE | |
[ $UNICODE -eq 2 ] && return 0 | |
[ $UNICODE -ne 2 ] && return 1 | |
) | |
} | |
run_tput () { | |
local arg_1=$1 | |
[ $TPUT_UNAVAILABLE -ne 0 ] && return 1 | |
$TPUT_RUNTIME "$arg_1" | |
return 0 | |
} | |
spinner () { | |
# Process Id of the previous running command | |
local pid=$! | |
run_tput civis | |
[ "$UNICODE_SUPPORT" == "Y" ] && spin="$CHAR_UNICODE_SPIN" || spin="$CHAR_ASCII_SPIN" | |
printf ' ' | |
local i=0 | |
while kill -0 $pid 2>/dev/null | |
do | |
i=$(( (i+1) % ${#spin} )) | |
printf "\b${spin:$i:1}" | |
sleep .1 | |
done | |
printf "\b \b" | |
run_tput cnorm | |
wait $pid | |
PID_STATUS=$? | |
} | |
function_exists () { | |
declare -f -F $1 > /dev/null | |
return $? | |
} | |
parse_yaml () { | |
local prefix=$2 | |
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034') | |
sed -ne "s|^\($s\):|\1|" \ | |
-e "s|^\($s\)\($w\)$s:$s[\"']\(.*\)[\"']$s\$|\1$fs\2$fs\3|p" \ | |
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 | | |
awk -F$fs '{ | |
indent = length($1)/2; | |
vname[indent] = $2; | |
for (i in vname) {if (i > indent) {delete vname[i]}} | |
if (length($3) > 0) { | |
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")} | |
printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3); | |
} | |
}' | |
} | |
contains_element () { | |
local e match="$1" | |
shift | |
for e; do [[ "$e" == "$match" ]] && return 0; done | |
return 1 | |
} | |
cleanup_tmp () { | |
[ $CLEANUP_TMP -ne 1 ] && return | |
rm -f $DOWNLOAD_TMP_PATH/$MANIFEST_FILE | |
} | |
# Downloader functions | |
download_curl () { | |
local arg_url="$1" | |
local arg_dst_file="$2" | |
if [ $DOWNLOAD_PROGRESS -eq 1 ]; then | |
$DOWNLOADER_RUNTIME -f -L --output "$DOWNLOAD_TMP_PATH/$arg_dst_file" --progress-bar "$arg_url" | |
res=$? | |
else | |
$DOWNLOADER_RUNTIME -f -L -s --output "$DOWNLOAD_TMP_PATH/$arg_dst_file" "$arg_url" | |
res=$? | |
fi | |
sleep 1 | |
return $res | |
} | |
download_wget () { | |
local arg_url="$1" | |
local arg_dst_file="$2" | |
if [ $DOWNLOAD_PROGRESS -eq 1 ]; then | |
$DOWNLOADER_RUNTIME --show-progress -q -O "$DOWNLOAD_TMP_PATH/$arg_dst_file" "$arg_url" | |
res=$? | |
else | |
$DOWNLOADER_RUNTIME -q -O "$DOWNLOAD_TMP_PATH/$arg_dst_file" "$arg_url" | |
res=$? | |
fi | |
return $res | |
} | |
download () { | |
local arg_url=$1 | |
local arg_dst_file=$2 | |
local downloader_name=$( basename $DOWNLOADER_RUNTIME ) | |
local function_name="download_${downloader_name}" | |
if ! function_exists $function_name; then | |
err_msg "No such function: ${function_name}." | |
fi | |
debug_msg "Downloading $arg_url as file $DOWNLOAD_TMP_PATH/$arg_dst_file" | |
$function_name "$arg_url" "$arg_dst_file" | |
return $? | |
} | |
# Self-check functions | |
check_unicode () { | |
test_unicode | |
local RC=$? | |
export UNICODE_SUPPORT=`[ $RC -eq 0 ] && echo "Y" || echo "N"` | |
unset test_unicode | |
} | |
check_which () { | |
$( which bash > /dev/null 2>&1 ) | |
return $? | |
} | |
check_app_exists () { | |
local app_name=$1 | |
which $app_name > /dev/null 2>&1 | |
return $? | |
} | |
check_downloader () { | |
debug_msg "Checking downloader availability" | |
local exit_status=1 | |
for downloader in ${DOWNLOADERS[@]}; do | |
local downloader_path=$( which $downloader 2>/dev/null; exit_status=$? ) | |
[ $exit_status -eq 0 ] && break | |
done | |
[ "$downloader_path" == "" ] && return 1 | |
echo $downloader_path | |
return 0 | |
} | |
check_tput () { | |
debug_msg "Checking tput availability" | |
local tput_path=$( which tput 2>/dev/null ) | |
res=$? | |
echo $tput_path | |
return $res | |
} | |
check_os () { | |
local os_name=$( uname -s | awk '{print tolower($0)}' ) | |
local supported_os=$( echo ${SUPPORTED_OS[@]} | awk '{print tolower($0)}' ) | |
contains_element $os_name ${supported_os[@]} || err_msg "Installer does not support '$os_name' operating system." | |
} | |
check_distribution () { | |
local distro_name='ubuntu' | |
echo $distro_name | |
} | |
check_distribution_version () { | |
local distro_version='18.04' | |
echo $distro_version | |
} | |
self_check () { | |
debug_msg "Self check" | |
check_unicode | |
check_which || err_msg "No 'which' found in PATH." | |
apps_to_check=( basename sed awk grep uname lsb_release cut uniq tr tar sha256sum ) | |
for app_name in ${apps_to_check[@]}; do | |
check_app_exists "$app_name" || err_msg "No '$app_name' found in PATH." | |
done | |
check_os | |
DOWNLOADER_RUNTIME=$( check_downloader ) | |
[ $? -ne 0 ] && err_msg "No suitable downloader found (one of: ${DOWNLOADERS[@]})." | |
TPUT_RUNTIME=$( check_tput ) | |
TPUT_UNAVAILABLE=$? | |
} | |
cache_sudo () { | |
# Just for getting password cached | |
sudo ls > /dev/null 2>&1 | |
} | |
# Manifest functions | |
manifest_check () { | |
debug_msg "Checking manifest" | |
local manifest_error="Manifest has improper format. Perhaps newer install script is required?" | |
eval $( parse_yaml "$DOWNLOAD_TMP_PATH/$MANIFEST_FILE" ) | |
# local var_name="${MANIFEST_DEPENDENCY_PREFIX}_ubuntu_default" | |
# [ -z ${!var_name+x} ] && err_msg "$manifest_error" | |
[ -z ${golem_releases_latest+x} ] && err_msg "$manifest_error" | |
[ -z ${golem_releases_published+x} ] && err_msg "$manifest_error" | |
local release_descriptions=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}" ) ) | |
[ ${#release_descriptions[@]} -eq 0 ] && err_msg "$manifest_error" | |
} | |
retrieve_manifest () { | |
debug_msg "Retrieving manifest" | |
rm -f $DOWNLOAD_TMP_PATH/${MANIFEST_FILE} > /dev/null 2>&1 | |
download "${MANIFEST_URL}" "${MANIFEST_FILE}" & | |
spinner_msg "Downloading manifest" || err_msg "Failed downloading manifest." | |
[ ! -f $DOWNLOAD_TMP_PATH/$MANIFEST_FILE ] && err_msg "Manifest file does not exist." | |
manifest_check | |
} | |
# Dependency functions | |
failed_dependency_install () { | |
local err_message=$1 | |
exec 2>&6 6>&- | |
[ -f $TMP_ERR_LOG ] && echo -e "\nCommand returned errors:\n------------------------" && cat $TMP_ERR_LOG >&2 && rm -f $TMP_ERR_LOG && echo | |
err_msg "${err_message}" | |
} | |
install_dependencies_ubuntu () { | |
local dependencies=$@ | |
debug_msg "Installing dependencies for Ubuntu" | |
exec 6>&2 2>$TMP_ERR_LOG | |
if [ ${SKIP_DEPS_UPDATE} -eq 0 ]; then | |
$( sudo apt-get update -y > /dev/null ) & | |
spinner_msg "Updating apt repositories" || failed_dependency_install "Failed updating apt repositories." | |
fi | |
if [[ ! -z "$UNHOLD_PACKAGES" && ${#UNHOLD_PACKAGES[@]} -gt 0 ]]; then | |
$( sudo apt-mark unhold ${UNHOLD_PACKAGES[@]} > /dev/null ) & | |
spinner_msg "Unsetting packages hold: ${UNHOLD_PACKAGES[@]}" || failed_dependency_install "Failed packages unhold." | |
fi | |
if [[ ! -z "$HOLD_PACKAGES" && ${#HOLD_PACKAGES[@]} -gt 0 ]]; then | |
$( sudo apt-mark unhold ${HOLD_PACKAGES[@]} > /dev/null ) & | |
spinner_msg "Unsetting packages hold: ${HOLD_PACKAGES[@]}" || failed_dependency_install "Failed packages unhold." | |
fi | |
$( sudo apt-get install -y ${dependencies[@]} > /dev/null ) & | |
spinner_msg "Installing dependencies" || failed_dependency_install "Failed dependency installation." | |
if [[ ! -z "$EXTRA_PACKAGES" && ${#EXTRA_PACKAGES[@]} -gt 0 ]]; then | |
$( sudo apt-get install -y ${EXTRA_PACKAGES[@]} > /dev/null ) & | |
spinner_msg "Installing extra dependencies" || failed_dependency_install "Failed extra dependency installation." | |
fi | |
if [[ ! -z "$HOLD_PACKAGES" && ${#HOLD_PACKAGES[@]} -gt 0 ]]; then | |
$( sudo apt-mark hold ${HOLD_PACKAGES[@]} > /dev/null ) & | |
spinner_msg "Setting packages on hold: ${HOLD_PACKAGES[@]}" || failed_dependency_install "Failed packages hold." | |
fi | |
exec 2>&6 6>&- | |
} | |
install_dependencies () { | |
local distro_name=$1 | |
local dependencies=${@:2} | |
debug_msg "Installing dependencies" | |
local function_name="install_dependencies_$distro_name" | |
if ! function_exists $function_name; then | |
err_msg "Cannot install dependencies. Distribution not supported: $distro_name. No such function: ${function_name}." | |
fi | |
$function_name "${dependencies[@]}" | |
} | |
resolve_dependencies () { | |
local distro_name=$1 | |
local distro_version=$2 | |
local dependency_var="${MANIFEST_DEPENDENCY_PREFIX}_${distro_name}_${distro_version}" | |
local references=( $( echo "${!dependency_var}" | grep -w -o -E -e "@[a-zA-Z0-9_]+" ) ) | |
local non_references=( $( echo "${!dependency_var}" | grep -o -P "(?:(?<=^)|(?<=\s))(?<!@)[a-zA-Z0-9-_.]+" ) ) | |
local result="${non_references[@]}" | |
for reference in ${references[@]}; do | |
local resolved_references=( $( resolve_dependencies "${distro_name}" "${reference:1}" ) ) | |
result+=" ${resolved_references[@]}" | |
done | |
echo "${result[@]}" | tr -s ' ' '\n' | sort -u | tr -s '\n' ' ' | |
} | |
install_docker_ubuntu () { | |
local docker_version=$1 | |
debug_msg "Installing docker on Ubuntu" | |
exec 6>&2 2>$TMP_ERR_LOG | |
$( sudo apt-get remove -y docker docker-engine docker.io > /dev/null ) & | |
spinner_msg "Removing obsolete docker" || failed_dependency_install "Failed removing obsolete docker." | |
if [[ ! -z "$REMOVE_DOCKER" && $REMOVE_DOCKER -eq 1 ]]; then | |
$( sudo systemctl stop docker > /dev/null ) & | |
spinner_msg "Stopping docker" || failed_dependency_install "Failed stopping docker." | |
$( sudo apt-get remove -y docker-ce docker-ce-cli ${REMOVE_EXTRA_PACKAGES[@]} > /dev/null ) & | |
spinner_msg "Removing installed docker-ce and extra packages" || failed_dependency_install "Failed removing docker-ce and extra packages." | |
fi | |
$( sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common > /dev/null ) & | |
spinner_msg "Installing docker dependencies" || failed_dependency_install "Failed installing docker dependencies." | |
$( download "$DOCKER_GPG_KEY" "docker-repo-key.gpg"; sudo apt-key add $DOWNLOAD_TMP_PATH/docker-repo-key.gpg > /dev/null ) & | |
spinner_msg "Adding docker repository GPG key" || failed_dependency_install "Failed adding docker repository GPG key." | |
$( sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" > /dev/null ) & | |
spinner_msg "Adding docker repository" || failed_dependency_install "Failed adding docker repository." | |
if [ $SKIP_DEPS_UPDATE -eq 0 ]; then | |
$( sudo apt-get update -y > /dev/null ) & | |
spinner_msg "Updating packages" || failed_dependency_install "Failed updating packages." | |
fi | |
local docker_version_to_install="docker-ce" | |
[ ! -z "$docker_version" ] && docker_version_to_install="docker-ce=${docker_version}" | |
$( sudo apt-get install -y --allow-change-held-packages ${docker_version_to_install} > /dev/null ) & | |
spinner_msg "Installing docker-ce" || failed_dependency_install "Failed installing docker-ce." | |
if [ -z "${SUDO_USER}" ]; then | |
$( sudo usermod -aG docker ${USER} ) & | |
else | |
$( sudo usermod -aG docker ${SUDO_USER} ) & | |
fi | |
spinner_msg "Add user to docker group." || failed_dependency_install "Cannot add user to docker group." | |
$( sudo systemctl restart docker ) & | |
spinner_msg "Restarting docker" || failed_dependency_install "Failed to restart docker." | |
$( sudo docker run hello-world > /dev/null 2>&1 ) & | |
spinner_msg "Testing docker is running" || failed_dependency_install "Docker cannot run hello-world. Testing failed." | |
exec 2>&6 6>&- | |
} | |
install_docker () { | |
local distro_name=$1 | |
local docker_version=$2 | |
local function_name="install_docker_$distro_name" | |
if ! function_exists $function_name; then | |
err_msg "Cannot install docker. Distribution not supported: $distro_name. No such function: ${function_name}." | |
fi | |
$function_name "${docker_version}" | |
} | |
check_package_installed_version_ubuntu () { | |
echo $(dpkg -l 2>/dev/null | grep "$@\s" | grep -E 'hi|ii' | head -1 | awk '{print $3}') | |
} | |
check_package_installed_version () { | |
local distro_name=$1 | |
local package_name=$2 | |
local function_name="check_package_installed_version_$distro_name" | |
if ! function_exists $function_name; then | |
err_msg "Cannot check package installed. Distribution not supported: $distro_name. No such function: ${function_name}." | |
fi | |
$function_name "${package_name}" | |
} | |
check_distro_installer_ubuntu () { | |
local ubuntu_installer_components=( apt-get add-apt-repository apt-key ) | |
for installer_component in ${ubuntu_installer_components[@]}; do | |
check_app_exists "$installer_component" || err_msg "No '$installer_component' found in PATH." | |
done | |
} | |
check_distro_installer () { | |
local distro_name=$1 | |
local function_name="check_distro_installer_$distro_name" | |
if ! function_exists $function_name; then | |
err_msg "Cannot check distro installer. Distribution not supported: $distro_name. No such function: ${function_name}." | |
fi | |
$function_name | |
} | |
parse_dependencies () { | |
debug_msg "Parse dependencies" | |
local distro_name=$( check_distribution ) | |
local supported_distros=( $( compgen -A variable | grep "${MANIFEST_DEPENDENCY_PREFIX}_" | cut -d_ -f8 | uniq ) ) | |
debug_msg "${MANIFEST_DEPENDENCY_PREFIX}" | |
debug_msg "Script supported distributions: ${supported_distros[@]}" | |
debug_msg "Found distribution name: $distro_name" | |
if ! contains_element "$distro_name" "${supported_distros[@]}"; then | |
err_msg "Linux distribution '$distro_name' is not supported by this installer." | |
fi | |
local distro_version=$( check_distribution_version | tr -s '.' '_' ) | |
local supported_versions=( $( compgen -A variable | grep "${MANIFEST_DEPENDENCY_PREFIX}_${distro_name}_" | cut -d_ -f9- | uniq ) ) | |
if ! contains_element "$distro_version" "${supported_versions[@]}"; then | |
if ! contains_element "default" "${supported_versions[@]}"; then | |
err_msg "Manifest file does not have dependency definition for this distribution version, nor default one." | |
else | |
distro_version="default" | |
fi | |
fi | |
debug_msg "Supported distribution version: $distro_version" | |
check_distro_installer "$distro_name" | |
[ $INSTALL_DOCKER -ne 0 ] && install_docker "$distro_name" "${DOCKER_VERSION}" | |
local dependencies=( $( resolve_dependencies "${distro_name}" "$distro_version" ) ) | |
install_dependencies "$distro_name" "${dependencies[@]}" | |
for after_dependency_func in ${AFTER_DEPENDENCY_INSTALL_FUNCTIONS[@]}; do | |
${after_dependency_func} "$distro_name" | |
done | |
} | |
# Extensions install | |
parse_extensions () { | |
debug_msg "Parse extensions for $install_release_version" | |
local install_release_version=$1 | |
local extensions_list=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_extensions" | cut -d_ -f8 | uniq ) ) | |
[ ${#extensions_list[@]} -eq 0 ] && debug_msg "No extensions found for release in manifest." && return | |
for extension in ${extensions_list[@]}; do | |
local extension_script_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_extensions_${extension}_script" | |
local extension_hash_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_extensions_${extension}_hash" | |
[[ -z ${extension_script_var} || "${!extension_script_var}" == "" ]] && warn_msg "Extension '${extension}' has no script defined in manifest. Skipping..." && continue | |
if [ $EXTENSION_HASH_CHECK -eq 1 ]; then | |
[[ -z ${extension_hash_var} || "${!extension_hash_var}" == "" ]] && warn_msg "Extension '${extension}' has no hash defined in manifest. Skipping..." && continue | |
fi | |
local extension_script=${!extension_script_var} | |
local extension_file=${extension_script##*/} | |
download "${extension_script}" "${extension_file}" & | |
spinner_msg "Downloading install script for extension '$extension'" || { warn_msg "Failed downloading extension script. Skipping..." && continue; } | |
if [ $EXTENSION_HASH_CHECK -eq 1 ]; then | |
local extension_file_hash=$( sha256sum ${DOWNLOAD_TMP_PATH}/${extension_file} | cut -d\ -f1 ) | |
[ "$extension_file_hash" != "${!extension_hash_var}" ] && warn_msg "Extension hash '${extension}' mismatch. Skipping..." && continue | |
fi | |
source "${DOWNLOAD_TMP_PATH}/${extension_file}" | |
done | |
} | |
# Installation functions | |
install_release () { | |
local release_file=$1 | |
local release_version=$2 | |
local release_links=${@:3} | |
debug_msg "Installing release" | |
exec 6>&2 2>$TMP_ERR_LOG | |
if [ ! -d $INSTALL_DESTINATION ]; then | |
sudo mkdir -p $INSTALL_DESTINATION > /dev/null || failed_dependency_install "Cannot create directory: $INSTALL_DESTINATION" | |
else | |
[ $OVERWRITE -ne 1 ] && failed_dependency_install "Installation destination path already exists: $INSTALL_DESTINATION" | |
warn_msg "Installation destination path already exists! Overwriting." | |
fi | |
$( sudo tar -C $INSTALL_DESTINATION -xzf $DOWNLOAD_TMP_PATH/$release_file --strip-components 1 > /dev/null ) & | |
spinner_msg "Extracting release archive ${release_file} to ${INSTALL_DESTINATION}" || failed_dependency_install "Failed extracting archive '${release_file}'." | |
if [ ${#release_links[@]} -ne 0 ]; then | |
for release_link in ${release_links[@]}; do | |
[ ! -f ${INSTALL_DESTINATION}/$release_link ] && warn_msg "Cannot symlink ${release_link}. File not found." && continue | |
$( sudo ln -fs ${INSTALL_DESTINATION}/$release_link $INSTALL_SYMLINK_PREFIX ) & | |
spinner_msg "Symlinking ${release_link} to ${INSTALL_SYMLINK_PREFIX}" || failed_dependency_install "Failed symlinking '${release_link}'." | |
done | |
fi | |
exec 2>&6 6>&- | |
} | |
install_component () { | |
local component_file=$1 | |
local component_name=$2 | |
local component_destination=$3 | |
[[ -z ${component_destination+x} || "$component_destination" == "" ]] && component_destination=$INSTALL_DESTINATION | |
local component_links=${@:4} | |
debug_msg "Installing release component $component_name" | |
exec 6>&2 2>$TMP_ERR_LOG | |
if [ ! -d $component_destination ]; then | |
sudo mkdir -p $component_destination > /dev/null || failed_dependency_install "Cannot create directory: $component_destination" | |
fi | |
$( sudo tar -C $component_destination -xzf $DOWNLOAD_TMP_PATH/$component_file --strip-components 1 > /dev/null ) & | |
spinner_msg "Extracting component archive ${component_file} to ${component_destination}" || failed_dependency_install "Failed extracting archive '${component_file}'." | |
if [ ${#component_links[@]} -ne 0 ]; then | |
for component_link in ${component_links[@]}; do | |
[ ! -f ${component_destination}/$component_link ] && warn_msg "Cannot symlink ${component_link}. File not found." && continue | |
$( sudo ln -fs ${component_destination}/$component_link $INSTALL_SYMLINK_PREFIX ) & | |
spinner_msg "Symlinking ${component_link} to ${INSTALL_SYMLINK_PREFIX}" || failed_dependency_install "Failed symlinking '${component_link}'." | |
done | |
fi | |
exec 2>&6 6>&- | |
} | |
parse_releases () { | |
local install_version=$1 | |
local release_latest=${!MANIFEST_RELEASES_LATEST} | |
[[ -z ${install_version+x} || "$install_version" == "" ]] && install_version=$release_latest | |
local release_published=( ${!MANIFEST_RELEASES_PUBLISHED} ) | |
contains_element $install_version ${release_published[@]} || err_msg "Manifest does not have Golem release '$install_version' in published versions." | |
local release_descriptions=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}" | cut -d_ -f4-6 | uniq ) ) | |
[ ${#release_descriptions[@]} -eq 0 ] && err_msg "Manifest does not have at least one release version description." | |
local release_descriptions_versions=( $( echo ${release_descriptions[@]} | tr -s '_' '.' ) ) | |
contains_element $release_latest ${release_descriptions_versions[@]} || err_msg "Manifest has latest release set, but no release description found." | |
contains_element $install_version ${release_descriptions_versions[@]} || err_msg "Manifest has no release '$install_version' description." | |
local install_release_version=$( echo $install_version | tr -s '.' '_' ) | |
local release_description=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}" ) ) | |
local release_status_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_status" | |
contains_element $release_status_var ${release_description[@]} || err_msg "Release description for version '$install_version' does not have 'status'." | |
local release_status=${!release_status_var} | |
[[ "$release_status" != "release" && $INSTALL_DEVELOP -ne 1 ]] && err_msg "You are trying to install development version, but no --develop flag was specified." | |
local release_url_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_url" | |
contains_element $release_url_var ${release_description[@]} || err_msg "Release description for version '$install_version' does not have 'url'." | |
local release_url=${!release_url_var} | |
local release_file=${release_url##*/} | |
local release_links=() | |
local release_links_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_links" | |
[[ -z $release_links_var || "${!release_links_var}" == "" ]] || release_links=( ${!release_links_var} ) | |
MANIFEST_DEPENDENCY_PREFIX="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_dependencies" | |
parse_extensions "${install_release_version}" | |
parse_dependencies | |
$( download "${release_url}" "${release_file}" ) & | |
spinner_msg "Downloading release ${install_version}" || err_msg "Failed downloading release '${install_version}'." | |
INSTALL_DESTINATION=$INSTALL_DESTINATION_PREFIX/$install_version | |
install_release "$release_file" "$install_version" "${release_links[@]}" | |
local component_install=0 | |
local release_components_vars=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components" ) ) | |
[ ${#release_components_vars[@]} -eq 0 ] && component_install=0 || component_install=1 | |
if [ $component_install -eq 1 ]; then | |
local release_components=( $( compgen -A variable | grep "${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components_" | cut -d_ -f8 | uniq ) ) | |
for release_component in ${release_components[@]}; do | |
local release_component_url_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components_${release_component}_url" | |
local release_component_url=${!release_component_url_var} | |
local release_component_file=${release_component_url##*/} | |
local release_component_path_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components_${release_component}_path" | |
local release_component_path="" | |
[ -z ${release_component_path_var+x} ] || release_component_path=$INSTALL_DESTINATION/${!release_component_path_var} | |
local release_component_links_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components_${release_component}_links" | |
local release_component_links=() | |
[ -z ${release_component_links_var+x} ] || release_component_links="${!release_component_links_var}" | |
local release_component_status_var="${MANIFEST_RELEASES_DESCRIPTIONS}_${install_release_version}_components_${release_component}_status" | |
local release_component_status=$DEFAULT_COMPONENT_STATUS | |
[[ -z ${release_component_status_var+x} || "${!release_component_status_var}" == "" ]] || release_component_status="${!release_component_status_var}" | |
local release_component_install=1 | |
[[ "$release_component_status" == "optional" && $INSTALL_OPTIONAL -eq 0 ]] && release_component_install=0 && warn_msg "Component ${release_component} is optional. Skipping... If you want to install it, rerun installer with --optional." | |
if [ $release_component_install -eq 1 ]; then | |
$( download "${release_component_url}" "${release_component_file}" ) & | |
spinner_msg "Downloading install component ${release_component}" || err_msg "Failed downloading install component '${release_component_file}'." | |
install_component "$release_component_file" "$release_component" "$release_component_path" "${release_component_links[@]}" | |
fi | |
done | |
fi | |
} | |
# Option parsing functions | |
print_usage () { | |
echo "Usage: $0 [-h] [-d][-D][-m URL][-o][-O][-t TMP][-V VER]" | |
} | |
print_help () { | |
print_banner | |
echo -e "Options:" | |
echo -e " -h --help Show help." | |
echo -e " -d --develop Install development version." | |
echo -e " -D --debug Show debug messages." | |
echo -e " -E --no-extensions Do not try to install extensions." | |
echo -e " -m --manifest-url URL Manifest URL." | |
echo -e " -o --optional Install optional components." | |
echo -e " -O --overwrite Overwrite existing installation." | |
echo -e " -s --symlink-prefix PREFIX Location of symlinks to binaries." | |
echo -e " --skip-deps-update Skip dependency update." | |
echo -e " -t --temp-path TMP Download temporary path (default: ${DOWNLOAD_TMP_PATH})." | |
echo -e " -V --version VER Install Golem version." | |
} | |
parse_options () { | |
while (( "$#" )); do | |
case "$1" in | |
'-h' | '--help') | |
print_help | |
exit 1 | |
;; | |
'-d' | '--develop') | |
INSTALL_DEVELOP=1 | |
;; | |
'-D' | '--debug') | |
DEBUG=1 | |
;; | |
'-E' | '--no-extensions') | |
NO_EXTENSIONS_INSTALL=1 | |
;; | |
'-o' | '--optional') | |
INSTALL_OPTIONAL=1 | |
;; | |
'-O' | '--overwrite') | |
OVERWRITE=1 | |
;; | |
'-m' | '--manifest-url') | |
shift | |
[[ -z $1 || "$1" == "" || "${1:0:1}" == "-" ]] && err_msg "--manifest-url requires URL argument." | |
MANIFEST_URL="$1" | |
;; | |
'-s' | '--symlink-prefix') | |
shift | |
[[ -z $1 || "$1" == "" || "${1:0:1}" == "-" ]] && err_msg "--symlink-prefix requires PREFIX argument." | |
INSTALL_SYMLINK_PREFIX="$1" | |
;; | |
'--skip-deps-update') | |
SKIP_DEPS_UPDATE=1 | |
;; | |
'-V' | '--version') | |
shift | |
[[ -z $1 || "$1" == "" || "${1:0:1}" == "-" ]] && err_msg "--version requires VER argument." | |
VERSION_TO_INSTALL=$1 | |
;; | |
'-t' | '--temp-path') | |
shift | |
[[ -z $1 || "$1" == "" || "${1:0:1}" == "-" ]] && err_msg "--temp-path requires TMP argument." | |
DOWNLOAD_TMP_PATH=$1 | |
[ ! -d $DOWNLOAD_TMP_PATH ] && err_msg "Temporary path '$DOWNLOAD_TMP_PATH' does not exist." | |
;; | |
*) | |
print_usage | |
err_msg "ERROR: Unknown option: $1" | |
exit 1 | |
;; | |
esac | |
shift | |
done | |
} | |
# Main function | |
main () { | |
parse_options $@ | |
print_banner | |
self_check | |
cache_sudo | |
retrieve_manifest | |
parse_releases "${VERSION_TO_INSTALL}" | |
info_msg "Golem has been installed succesfully." | |
} | |
main $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment