shoestrap/helpers/default
2021-07-26 21:40:50 -07:00

446 lines
9.6 KiB
Bash

#!/bin/bash
##############################################################################
# DO NOT MODIFY THIS FILE. Instead, modify 'helpers/custom'.
##############################################################################
COOKBOOK_NAME="$(basename "$0")"
if [ -z "$SHOESTRAP_BASE" ]; then
DIR="$( cd "$( dirname "$0" )" && pwd )"
else
DIR="$SHOESTRAP_BASE"
fi
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shoestrap"
#
# Run a given recipe.
#
# Arguments can be passed to the 'recipe' function. They will be accessible by
# the recipe as $2, $3, $4, etc.
#
recipe () {
CURRENT_RECIPE_NAME=$1
DEFAULT_ASSETS_PATH="$DIR/assets/default/$CURRENT_RECIPE_NAME"
COOKBOOK_ASSETS_PATH="$DIR/assets/$COOKBOOK_NAME/$CURRENT_RECIPE_NAME"
local default_recipe="$DIR/recipes/default/$CURRENT_RECIPE_NAME"
local cookbook_recipe="$DIR/recipes/$COOKBOOK_NAME/$CURRENT_RECIPE_NAME"
if [ -f "$cookbook_recipe" ]; then
log "Running recipe '$cookbook_recipe'..." 1
separator
# shellcheck source=/dev/null
. "$cookbook_recipe"
elif [ -f "$default_recipe" ]; then
log "Running recipe '$default_recipe'..." 1
separator
# shellcheck source=/dev/null
. "$default_recipe"
else
error "Could not find recipe for '$CURRENT_RECIPE_NAME'. Fail!"
fi
cd "$DIR" || error "Failed to find recipe"
}
#
# Prints the 'finished' banner.
#
finished () {
spacer 1
separator "="
echo " FINISHED: '$COOKBOOK_NAME'"
separator "="
spacer 1
}
#
# Writes a log line to the screen
#
# If specified, the first parameter is the number of empty lines to print
# before the log message.
#
# If specified, the second parameter is the number of empty lines to print
# before the log message.
#
log () {
if [[ $2 -gt 0 ]]; then
spacer "$2"
fi
echo " * $1"
if [[ $3 -gt 0 ]]; then
spacer "$3"
fi
}
#
# Writes an error log line to the screen and exit with an error code.
#
error () {
spacer 2
echo " -> $1"
spacer 2
exit 1
}
#
# Write one or many empty lines to the screen.
#
spacer () {
if [ -n "$1" ]; then
local spaces=$1
else
local spaces=1
fi
for (( i=0; i<spaces; i++ )) do
echo ""
done
}
#
# noop
#
noop () {
return 0
}
#
# Write a separator to the screen.
#
# You can optionally specify the separator character. Default is '-'.
#
separator () {
if [ -n "$1" ]; then
local char=$1
else
local char='-'
fi
local width=""
width=$(tput cols)
for (( i=0; i < width-2; i++ )) do
local output="$output$char"
done
echo "$output"
}
#
# Update packages in package manager.
#
sudo_package_update () {
log "Updating package manager..." 0 1
detect_package_manager
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
sudo apt-get update -y
elif [ "$PACKAGE_MANAGER" == 'yum' ]; then
sudo yum check-update -y
elif [ "$PACKAGE_MANAGER" == 'port' ]; then
sudo port selfupdate
elif [ "$PACKAGE_MANAGER" == 'brew' ]; then
brew update
elif [ "$PACKAGE_MANAGER" == 'apk' ]; then
true
else
error "Unknown package manager: $PACKAGE_MANAGER"
fi
# shellcheck disable=2181
if [ $? -ne 0 ]; then
error "An error occured while updating packages. Fail!"
else
spacer 2
fi
}
#
# Install a package or packages through package manager
#
sudo_package () {
log "Installing packages '$*'..."
detect_package_manager
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
# shellcheck disable=2086,2048
sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y $*
elif [ "$PACKAGE_MANAGER" == 'yum' ]; then
# shellcheck disable=2086,2048
sudo yum install -y $*
elif [ "$PACKAGE_MANAGER" == 'port' ]; then
# Unintuitive, but this skips all promps which should assume Y
# shellcheck disable=2086,2048
sudo port -N install $*
elif [ "$PACKAGE_MANAGER" == 'brew' ]; then
# shellcheck disable=2086,2048
brew install $*
elif [ "$PACKAGE_MANAGER" == 'apk' ]; then
# shellcheck disable=2086,2048
apk add $*
else
error "Unknown package manager: $PACKAGE_MANAGER"
fi
# shellcheck disable=2181
if [ $? -ne 0 ]; then
error "An error occured while installing packages. Fail!"
else
spacer 2
fi
}
#
# Determine if a package is installed or not.
#
# If package is installed, function will return 0. If not, it will return 1.
#
test_package_installed () {
detect_package_manager
# When many packages are specified, skip test.
if [ $# -gt 1 ]; then
return 1
fi
if [ "$PACKAGE_MANAGER" == 'apt-get' ]; then
dpkg-query -l "$1" | grep -q ^.i
return $?
fi
# Don't know how to detect if a package is installed with other package managers.
return 1
}
#
# Determine which package manager is in use on the system.
#
detect_package_manager () {
if [ "$PACKAGE_MANAGER" != "" ]; then
return 0
fi
if command_exist apt-get; then
PACKAGE_MANAGER='apt-get'
elif command_exist yum; then
PACKAGE_MANAGER='yum'
elif command_exist port; then
PACKAGE_MANAGER='port'
elif command_exist brew; then
PACKAGE_MANAGER='brew'
elif command_exists apk; then
PACKAGE_MANAGER='apk'
else
error "Could not find a package manager. Fail!"
fi
log "Detected package manager: $PACKAGE_MANAGER"
return 0
}
#
# Determines if a command exist on the system.
#
command_exist () {
command -v "$1" > /dev/null 2>&1;
}
#
# Copy a file from the assets folder to the specified location.
#
copy () {
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
local target="$2"
if [ -f "$cookbook_assets_source" ]; then
log "Copying $cookbook_assets_source to $target..."
cp "$cookbook_assets_source" "$target"
elif [ -f "$default_assets_source" ]; then
log "Copying $default_assets_source to $target..."
cp "$default_assets_source" "$target"
else
error "Could not find '$1' to copy. Fail!"
fi
}
#
# Link a file from the assets folder to the specified location.
#
link () {
local src="$1"
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
local target="$2"
if [ -f "$src" ]; then
src="$src"
elif [ -d "$src" ]; then
src="$src"
elif [ -f "$cookbook_assets_source" ]; then
src="$cookbook_assets_source"
elif [ -f "$default_assets_source" ]; then
src="$default_assets_source"
elif [ -d "$cookbook_assets_source" ]; then
src="$cookbook_assets_source"
elif [ -d "$default_assets_source" ]; then
src="$default_assets_source"
else
error "Could not find '$1' to link Fail!"
fi
ln -s "$src" "$target"
}
#
# Attempt to link a file if it doesn't already exist
#
try_link () {
local src="$1"
local cookbook_assets_source="$COOKBOOK_ASSETS_PATH/$1"
local default_assets_source="$DEFAULT_ASSETS_PATH/$1"
local target="$2"
if [ -f "$src" ]; then
src="$src"
elif [ -d "$src" ]; then
src="$src"
elif [ -f "$cookbook_assets_source" ]; then
src="$cookbook_assets_source"
elif [ -f "$default_assets_source" ]; then
src="$default_assets_source"
elif [ -d "$cookbook_assets_source" ]; then
src="$cookbook_assets_source"
elif [ -d "$default_assets_source" ]; then
src="$default_assets_source"
else
error "Could not find '$1' to link Fail!"
fi
if [ -L "$2" ] && [ "$(readlink "$2")" == "$src" ] ; then
log "Link already exists: $2"
else
log "Creating link: $2 -> $src"
link "$1" "$2"
fi
}
#
# Add a user to the system.
#
add_user () {
local user=$1
local pass=$2
local args=$3
if id "$user" > /dev/null 2>&1 ; then
log "User $user already exists. Skipped creation."
else
log "Adding user $user..."
[ "$pass" == "" ] && pass=generate_password
if [[ "$args" != *nohome* ]]; then
/usr/sbin/useradd --password "$(openssl passwd -crypt "$pass")" --create-home "$user" --shell /bin/bash
else
/usr/sbin/useradd --password "$(openssl passwd -crypt "$pass")" "$user" --shell /bin/bash
fi
fi
}
#
# Generate a random password.
#
generate_password() {
local l=$1
[ "$l" == "" ] && l=8
tr -dc A-Za-z0-9_ < /dev/urandom | head -c ${l} | xargs
}
#
# Run a command as another user
#
run_as () {
local user=$1
local cmd=$2
log "Running command as '$user'..."
log "$cmd"
# sudo -u $user -H -s /bin/bash -c "$cmd"
# sudo -u $user -s /bin/bash -i "$cmd"
su -c "$cmd" -s /bin/bash "$user"
}
#
# Add line to a file if line is not already present
#
add_line () {
local line="$1"
local file="$2"
grep "$line" "$file" > /dev/null 2>&1
# shellcheck disable=2181
if [ $? -ne 0 ]; then
log "Adding '$line' to '$file'..."
echo "$line" >> "$file"
else
log "'$line' already in '$file'. Skipping."
fi
}
#
# Write a warning if user is not root.
#
warn_if_not_root () {
[ "$(id -u)" = "0" ] ||
{ echo "WARNING: You are NOT running this script as 'root'. You might want to consider that..."; }
}
#
# Stops the execution of the script if user is not root.
#
fail_if_not_root () {
[ "$(id -u)" = "0" ] || { echo "You must run this as 'root'. Exiting."; exit 1; }
}
#
# Checks if a certain element has already been installed.
#
is_installed () {
local args=$*
local name=${args//[ \/:@]/-}
if [[ -f "$CONFIG_DIR/installed/$name" ]]; then
log "'$name' is already installed."
return 0
else
log "'$name' is not installed."
return 1
fi
}
#
# Sets an element as installed.
#
set_installed () {
local args=$*
local name=${args//[ \/:@]/-}
mkdir -p "$CONFIG_DIR/installed"
touch "$CONFIG_DIR/installed/$name"
}
#
# Promts a user for a Yn confirmation
#
prompt_yn () {
read -p "$1 [y/n] " -n 1 -r
echo # move to a new line
if [[ $REPLY =~ ^[Yy]$ ]]; then
return 0
fi
return 1
}