#! /usr/bin/env bash ########_ App list # this is a reference template # function _app_nosudo_template_function() { # In function name `nosudo_` means, sudo isn't allowed, if replaced by # `sudo_`, installtion will require sudo, or it can be `auto_` # # APP_TYPE='' # bash-url, deb-github-release, deb-url # APP_ADDRESS='' # bash-url: # # The complete URL to the installation bash script # # deb-github-release: # # Owner/RepoName from the GitHub URL # APP_RELEASE='' # Used by deb-github-release, default is 'latest' # } # this is a reference custom template # function _app_template_function_custom() { # } function _app_sudo_gcm() { # Installs GitCredentialManager from Microsoft APP_TYPE='deb-github-release' APP_ADDRESS='GitCredentialManager/git-credential-manager' } function _app_nosudo_homebrew() { # Installs HomeBrew APP_TYPE='bash-url' APP_ADDRESS='https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh' } function _app_sudo_gcloud_custom() { if [[ ! -r "/etc/apt/sources.list.d/packages.cloud.google.com" ]]; then eval $(error 1 \ "Google Cloud Platform sources are not installed yet, please run 'pqb-add-apt-repo gcloud' first" \ ) || exit $? exit 1 fi apt install google-cloud-sdk-gke-gcloud-auth-plugin google-cloud-cli kubectl } function _app_sudo_systeroid_custom() { if [[ -n "$(type cargo 2>/dev/null)" ]]; then cargo install systeroid cargo install systeroid-tui else DL_URL=$( \ get-github-release.sh orhun/systeroid '' 'x86_64-unknown-linux-gnu.tar.gz' \ | grep 'tar.gz$' \ ) DL_PATH=$(download_temp $DL_URL) DL_DIR=$(dirname $DL_PATH) echo "Extracting..." tar zxC "$DL_DIR" -f "$DL_PATH" SRC_DIR=$( \ find "$DL_DIR" -mindepth 1 -maxdepth 1 -type d -not -name '.' \ | head -1 \ ) echo "Installing into /usr/local/bin..." mv "$SRC_DIR/systeroid"* /usr/local/bin [[ -n "$DL_DIR" && "$DL_DIR" =~ "/tmp/tmp." ]] && rm -R "$DL_DIR/" fi } function _apt_sudo_rstudio() { APP_TYPE='deb-url' APP_ADDRESS=$( \ wget -qO- https://rstudio.com/products/rstudio/download/ \ | grep -Eoi ']+>' | grep -Eo 'href="[^\"]+"' \ | grep -Eo '(http|https)://download.*\.deb' \ | grep 'jammy' \ ) } function _app_sudo_docker_system_custom() { if [[ ! -r "/etc/apt/sources.list.d/download.docker.com.list" ]]; then eval $(error 1 \ "Docker sources are not installed yet, please run 'pqb-add-apt-repo docker' first" \ ) || exit $? exit 1 fi [[ -z "$(type -fP docker)" ]] \ && echo "Installting docker-ce and related packages..." \ && DEBIAN_FRONTEND=noninteractive apt-get install --yes docker-ce docker-ce-cli containerd.io docker-compose-plugin \ && printf "\n\ndocker installed\n\n" CUR_USER=$USER [[ -n "$SUDO_USER" ]] \ && CUR_USER=$SUDO_USER echo "Adding current user ($CUR_USER) to the 'docker' group..." usermod --groups docker --append $CUR_USER if [[ ! -x /usr/local/bin/compose-switch ]]; then echo "Setting up docker-switch for docker-compose backward compatibility..." curl -fL https://raw.githubusercontent.com/docker/compose-switch/master/install_on_linux.sh | sh update-alternatives --install /usr/local/bin/docker-compose docker-compose /usr/local/bin/compose-switch 99 fi } ############ Script Logic starts here set -e SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) USER_HOME=$HOME [[ -n "${SUDO_USER}" ]] && USER_HOME="$(eval "echo ~${SUDO_USER}")" . ${SHRC_D:-$USER_HOME/.pqb.shrc.d}/01_util.functions get_clean_path() { sed 's/ *:\?$//g;s/`/``/g;s/:/`:`/g;s/\\`:`/\\:/g;' <<< $1 | \ awk -v RS='`:`' -v ORS='`:`' '!arr[$0]++' | \ sed 's/`:`/:/g;s/:$//g' } #PATH=$( get_clean_path "${PATH}:${SCRIPT_DIR}" ) #echo $PATH function download_temp() { local APP_ADDRESS=${1:-${APP_ADDRESS}} local DL_URL="${1}" local DL_FILENAME="${2:-${DL_URL##*/}}" local DL_DIR=$(mktemp -dt) pushd "$DL_DIR" > /dev/null || return $? # Download the .targz file echo "Downloading $DL_FILENAME to $DL_DIR..." 1>&2 wget -q "$DL_URL" && [[ -n "$SUDO_USER" ]] && chown -R $SUDO_USER "$DL_DIR" popd > /dev/null || return $? printf "${DL_DIR}/${DL_FILENAME}" } function install_app_bash_url() { local APP_ADDRESS=${1:-${APP_ADDRESS}} /bin/bash -c "$(curl -fsSL ${APP_ADDRESS})" } function install_app_deb_url() { local APP_ADDRESS=${1:-${APP_ADDRESS}} install-deb-from-web.sh "${APP_ADDRESS}" } function install_app_deb_github_release() { local APP_PROJECT=${1:-${APP_ADDRESS}} local APP_RELEASE=${2:-${APP_RELEASE:-latest}} install_app_deb_url $( \ get-github-release.sh "${APP_PROJECT}" "${APP_RELEASE}" \ ) } # The function that does the _Heavy Lifting_. # see the code that follows for the parameter signature function install_app() { local allFuncs=$( printf '%s\n' $(get_app_install_functions) $allFuncs | grep "_${1}\(_custom\)\?$" ) local okFuncs=$allFuncs if [[ -n $okFuncs ]]; then if [[ $EUID -ne 0 ]]; then okFuncs=$(printf '%s\n' $okFuncs | grep -v "^sudo_") else okFuncs=$(printf '%s\n' $okFuncs | grep -v "^nosudo_") fi if [[ -n $okFuncs ]]; then okFuncs=$(printf '%s\n' $okFuncs | head -1) if [[ "$(type -t _app_${okFuncs})" != 'function' \ && "$(type -t _app_${okFuncs}_custom)" != 'function' ]]; then unset okFuncs fi fi if [[ -n $okFuncs ]]; then if [[ "$okFuncs" =~ "${1}_custom" ]]; then eval "_app_$okFuncs" return $? else eval "_app_$okFuncs" || return $? printf "%s=%s\n" \ 'APP_TYPE' "${APP_TYPE}" \ 'APP_ADDRESS' "${APP_ADDRESS}" \ 'APP_RELEASE' "${APP_RELEASE}" #echo \ eval "install_app_$(echo ${APP_TYPE} | sed 's/-/_/g;')" fi else echo "Failed to launch $allFuncs" return 1 fi else echo "Could not find installation instructions for ${1}" return 1 fi echo "App $1 installed" } function get_app_install_functions() { typeset -f \ | grep '^_app_' | sed 's/^_app_//; s/ () *$//;' } function usage() { printf " %s\n" \ "Usage:" \ " $0 [-v[v]] " \ " [--no-init] [--no-overwrite] " \ " all|[ ...] " \ "" \ "Apps: $( \ printf "\n %s" $( \ get_app_install_functions \ | sed 's/_custom$//' \ | sed 's/^\([^_]*sudo[^_]*\)_\(.*\)$/\2(\1)/' \ | sort \ ))" \ "" \ "Options:" \ " --no-init - skip initialization." \ " -v[v] - script verbosity, equivalent to set -x and set -xv" \ "" } function main() { [[ ${#APP_LIST[@]} -eq 0 ]] && usage && return 1 _OS=$(lsb_release -is | awk '{ print tolower($0) }') [[ $_OS == 'pop' ]] && _OS='ubuntu' _REL=$(lsb_release -rs) # Release _CNM=$(lsb_release -cs) # CodeName _ARC=$(dpkg --print-architecture) # Architecture ANSI_Cyan "Initializing: Installing basic packages..."; echo if [[ -n "$SHOULD_INIT" ]]; then # Make sure the /usr/share/keyrings dir exists mkdir -p /usr/share/keyrings 2>&1 > /dev/null # Make sure all of the basic required tools are installed for the code # below to work apt-get install --yes --no-install-recommends \ curl gnupg software-properties-common apt-transport-https fi ANSI_Green "Done."; echo while read r; do ANSI_Cyan "Installing $r..."; echo install_app $r || return 2 ANSI_Green "Installation of $r completed."; echo done < <(printf "%s\n" "${APP_LIST[@]}") [[ -z "${SUDO_USER}" ]] && exec $SHELL \ || echo 'It is recommended that you restart your shell (exec $SHELL)' } # Iterate through stdin or parameters if [[ $# == 0 ]]; then usage else APP_LIST=() _SHOULD_INIT=1 READCMD='printf "%s\n" "${@}"' [[ $# == 1 && $1 == '-' ]] && READCMD='cat - ' while read a; do # Switch on _YES [[ "$a" == "-v" ]] && set -x && continue [[ "$a" == "-vv" ]] && set -xv && continue [[ "$a" == "--no-init" ]] && unset _SHOULD_INIT && continue # Add app [[ -n "$a" ]] && APP_LIST+=("$a") done < <( eval $READCMD ) main fi