diff --git a/README.md b/README.md index 675148dd..40ed0151 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ If you have questions or would like to contribute, I have a sub discord category * [Pod](#pod) * [PVC](#pvc) * [Self-Update](#self-update) + * [Sync](#sync) * [Update](#update) * [How to Install](#how-to-install) * [How to Update](#how-to-update) @@ -125,7 +126,12 @@ ___ |------------|--------------------|-------------------------------------------| | --major | --major | Includes major updates when self-updating | +
+ +### Sync +> heavyscript sync +Syncs the catalog.
@@ -155,19 +161,51 @@ ___ ## How to Install -### One Line Install -``` +HeavyScript can be installed in two different ways depending on your needs and privileges on the system: + +### Option 1: Non-Privileged Install (Regular User) + +> This installation method is suitable if you don't have root access or prefer not to install HeavyScript with elevated privileges. + +**Installation Command:** +```bash curl -s https://raw.githubusercontent.com/Heavybullets8/heavy_script/main/functions/deploy.sh | bash && source "$HOME/.bashrc" 2>/dev/null && source "$HOME/.zshrc" 2>/dev/null ``` -This will: -- Download HeavyScript, then place you on the latest release -- Place HeavyScript in `/root` -- Make HeavyScript executable -- Allow you to run HeavyScript from any directory with `heavyscript` - > This does not include Cron Jobs, see the Cron section for more information. +**What This Does:** +- Downloads and places HeavyScript in your user directory. +- Makes HeavyScript executable. +- Allows you to run HeavyScript from any directory using `heavyscript`. + +**Note:** +- Without root privileges, the script will not create a system-wide symlink in `/usr/local/bin`. +- You might see a warning message indicating the lack of root privileges. You can proceed without root access, but you'll need to run HeavyScript with root privileges at least once to create the system-wide symlink, if required. + +### Option 2: Privileged Install (Root or Sudo) + +> If you have root access or can use `sudo`, this method will set up HeavyScript for all users on the system. + +**Installation Command:** +```bash +curl -s https://raw.githubusercontent.com/Heavybullets8/heavy_script/main/functions/deploy.sh | sudo bash && source "$HOME/.bashrc" 2>/dev/null && source "$HOME/.zshrc" 2>/dev/null +``` + +**What This Does:** +- Installs HeavyScript with root privileges. +- Creates a system-wide symlink in `/usr/local/bin`, making HeavyScript accessible to all users. +- Downloads and places HeavyScript in the root directory (`/root`). +- Makes HeavyScript executable and accessible system-wide. + +**Note:** +- This method requires root access or sudo privileges. +- It's recommended for environments where HeavyScript needs to be accessible to multiple users. -From here, you can just run HeavyScript with `heavyscript -ARGUMENTS` +--- + +### Choosing the Right Option: + +- **Non-Privileged Install:** Choose this if you're more concerened with security and want to keep HeavyScript isolated to your user account, at least during the initial setup. +- **Privileged Install:** Choose this if you are less concerened about security and want to make HeavyScript accessible to all users on the system, including the root and sudo user.
@@ -227,34 +265,33 @@ ___ ### How to Create a Cron Job -1. TrueNAS SCALE GUI -2. System Settings -3. Advanced -4. Cron Jobs - 1. Click Add +To automate tasks using HeavyScript, you can create a cron job. Here's how to set it up in TrueNAS SCALE: + +1. Navigate to the TrueNAS SCALE GUI. +2. Go to **System Settings** > **Advanced**. +3. Click on **Cron Jobs**. +4. Click **Add** to create a new cron job. ![image](https://user-images.githubusercontent.com/20793231/229404447-6836ff1f-ba28-439e-99fe-745371f0f24c.png) +### Important Note on the Command Path +The command for the cron job should use the full path to the `heavy_script.sh` file. This path depends on the user who installed HeavyScript. For instance, if you installed HeavyScript as a non-root user, replace `/root` with your home directory path. -- Command: `bash /root/heavy_script/heavy_script.sh update` - > The `bash`, as well as the full path to the script is required for cron jobs to work properly. -- Run as: root - > Running as root is required for the script to work properly. -- Schedule: I run mine daily at 4:00 AM -- Hide Standard Output: Unchecked -- Hide Standard Error: Unchecked - > Keep these both unchecked so you can recive an email. +> You can find your home directory path by running `echo $HOME` in the terminal. +### Cron Job Settings -
+- **Command:** Use the full command with the correct path, as shown in the examples above. The `bash` prefix and the full path are required for proper execution. +- **Run as:** Typically, you should run the script as the user who installed HeavyScript. If it was installed with root privileges, use `root`. +- **Schedule:** Choose the frequency and time for the script to run. For example, daily at 4:00 AM. +- **Hide Standard Output/Error:** Uncheck these options if you wish to receive email notifications about the cron job's output and errors. ### My Personal Cron Job +Here's an example of how I set up my personal cron job: + ``` bash /root/heavy_script/heavy_script.sh update --backup 14 --concurrent 10 --prune --rollback --sync --self-update ``` - -
-
- +> Remember to adjust the path in the command based on where HeavyScript is installed and the user account used for installation. diff --git a/bin/heavyscript b/bin/heavyscript index c4e05d86..c275897f 100644 --- a/bin/heavyscript +++ b/bin/heavyscript @@ -4,20 +4,29 @@ set -Eeuo pipefail find_script_dir() { local home_dirs - home_dirs=$(getent passwd | \ - cut -d: -f6 | \ - sort -u | \ - grep -vE '/var/|/run/|/bin|/dev|/nonexistent|/srv/tftp|usr/share/man|^/$') + mapfile -t home_dirs < <(cli -m csv -c "account user query home,builtin" | grep ",false" | grep -v "nonexistent," | awk -F ',' '{print $1}') - for home_dir in $home_dirs; do + for home_dir in "${home_dirs[@]}"; do if [[ -d "$home_dir/heavy_script" ]]; then echo "$home_dir/heavy_script" return fi done - >&2 echo "Error: heavy_script directory not found." - exit 1 + err_exit "Error: heavy_script directory not found." +} + +get_user_home() { + local user_home + + if [[ $EUID -eq 0 ]]; then # Script is running as root + # Use SUDO_USER if set, otherwise fall back to root's home + user_home=$(getent passwd "${SUDO_USER:-root}" | cut -d: -f6) + else # Script is run by a regular user + user_home=$HOME + fi + + echo "$user_home" } err_exit() { @@ -25,26 +34,23 @@ err_exit() { exit "${2:-1}" } -if [[ -d "/root/heavy_script" ]]; then +# Use get_user_home to determine the home directory and check for the script +user_home=$(get_user_home) +if [[ -d "$user_home/heavy_script" ]]; then + script_dir="$user_home/heavy_script" +elif [[ -d "/root/heavy_script" ]]; then script_dir="/root/heavy_script" -elif [[ $EUID -eq 0 && -n ${SUDO_USER:-} && -d "/home/$SUDO_USER/heavy_script" ]]; then - script_dir="/home/$SUDO_USER/heavy_script" -elif [[ -d "$HOME/heavy_script" ]]; then - script_dir="$HOME/heavy_script" else - script_dir=$(find_script_dir) + script_dir=$(find_script_dir) # Fallback to find_script_dir if not found fi if [[ ! -d "$script_dir" ]]; then err_exit "Error: $script_dir does not exist." fi -( - # Change to the script directory - if ! cd "$script_dir" ; then - err_exit "Error: Failed to change to $script_dir" - fi +# Change to the script directory and execute heavy_script.sh +if ! cd "$script_dir" ; then + err_exit "Error: Failed to change to $script_dir" +fi - # Pass all arguments '$@' to heavy_script.sh - bash ./heavy_script.sh "$@" -) \ No newline at end of file +bash ./heavy_script.sh "$@" \ No newline at end of file diff --git a/functions/deploy.sh b/functions/deploy.sh index b54fcf7f..83936270 100644 --- a/functions/deploy.sh +++ b/functions/deploy.sh @@ -1,19 +1,26 @@ #!/bin/bash -# colors -reset='\033[0m' -red='\033[0;31m' -yellow='\033[1;33m' -green='\033[0;32m' -blue='\033[0;34m' - +get_user_home() { + local user_home + + if [[ $EUID -eq 0 ]]; then # Script is running as root + # Use SUDO_USER if set, otherwise fall back to root's home + user_home=$(getent passwd "${SUDO_USER:-root}" | cut -d: -f6) + else # Script is run by a regular user + user_home=$HOME + fi -# Check if user has a home -if [[ -z "$HOME" || $HOME == "/nonexistent" ]]; then - echo -e "${red}This script requires a home directory.${reset}" >&2 - exit 1 -fi + echo "$user_home" +} +get_invoking_user() { + if [[ $EUID -eq 0 ]]; then # Script is running as root + # Use SUDO_USER if set, otherwise fall back to root + echo "${SUDO_USER:-root}" + else # Script is run by a regular user + whoami + fi +} update_repo() { local script_dir="$1" @@ -31,16 +38,37 @@ update_repo() { fi } +# colors +reset='\033[0m' +red='\033[0;31m' +yellow='\033[1;33m' +green='\033[0;32m' +blue='\033[0;34m' # Define variables +USER_HOME=$(get_user_home) script_name='heavyscript' -script_dir="$HOME/heavy_script" -user_bin_dir="$HOME/bin" +script_dir="$USER_HOME/heavy_script" +user_bin_dir="$USER_HOME/bin" system_bin_dir="/usr/local/bin" user_script_wrapper="$user_bin_dir/$script_name" system_script_wrapper="$system_bin_dir/$script_name" main() { + # Check if user has a home + if [[ -z "$USER_HOME" || $USER_HOME == "/nonexistent" ]]; then + echo -e "${red}This script requires a home directory.${reset}" >&2 + echo -e "${red}Please create a home directory for the user.${reset}" >&2 + echo -e "${red}You can do so under the credentials tab in the Truenas SCALE GUI${reset}" >&2 + exit 1 + fi + + if [[ $EUID -ne 0 ]]; then + echo -e "${yellow}Warning: The script is not running with root privileges. To create a symlink in ${blue}$system_bin_dir${yellow}, please rerun the script with sudo or as the root user.${reset}" + echo -e "${yellow}You can exit now with CTRL+C to rerun with sudo, or wait 10 seconds to continue without creating the system-wide symlink.${reset}" + sleep 10 + fi + # Check if the script repository already exists if [[ -d "$script_dir" ]]; then echo -e "${yellow}The ${blue}$script_name${yellow} repository already exists.${reset}" @@ -68,7 +96,7 @@ main() { else # Clone the script repository echo -e "${blue}Cloning $script_name repository...${reset}" - cd "$HOME" || exit 1 + cd "$USER_HOME" || exit 1 if ! git clone "https://github.com/Heavybullets8/heavy_script.git" &>/dev/null; then echo -e "${red}Failed to clone the repository${reset}" exit 1 @@ -90,33 +118,48 @@ main() { mkdir "$user_bin_dir" fi - # Create symlink inside user's bin - echo -e "${blue}Creating $user_script_wrapper wrapper...${reset}" - ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" - chmod +x "$script_dir/bin/$script_name" - - # Create symlink inside system's bin - echo -e "${blue}Creating $system_script_wrapper wrapper...${reset}" - sudo ln -sf "$script_dir/bin/$script_name" "$system_script_wrapper" - sudo chmod +x "$script_dir/bin/$script_name" + if [[ $EUID -ne 0 ]]; then + echo -e "${yellow}Warning: Skipping system-wrapper...${reset}" + # Create symlink inside user's bin only + echo -e "${blue}Creating $user_script_wrapper wrapper...${reset}" + ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" + chmod +x "$script_dir/bin/$script_name" + else + # Create symlink inside both user's and system's bin + echo -e "${blue}Creating $user_script_wrapper and $system_script_wrapper wrappers...${reset}" + ln -sf "$script_dir/bin/$script_name" "$user_script_wrapper" + ln -sf "$script_dir/bin/$script_name" "$system_script_wrapper" + chmod +x "$script_dir/bin/$script_name" + chmod +x "$system_script_wrapper" + fi echo - # Add $HOME/bin to PATH in .bashrc and .zshrc + # Add $USER_HOME/bin to PATH in .bashrc and .zshrc for rc_file in .bashrc .zshrc; do - if [[ ! -f "$HOME/$rc_file" ]]; then - echo -e "${blue}Creating $HOME/$rc_file file...${reset}" - touch "$HOME/$rc_file" + if [[ ! -f "$USER_HOME/$rc_file" ]]; then + echo -e "${blue}Creating $USER_HOME/$rc_file file...${reset}" + touch "$USER_HOME/$rc_file" fi - if ! grep -q "$user_bin_dir" "$HOME/$rc_file"; then + if ! grep -q "$user_bin_dir" "$USER_HOME/$rc_file"; then echo -e "${blue}Adding $user_bin_dir to $rc_file...${reset}" - echo "export PATH=$user_bin_dir:\$PATH" >> "$HOME/$rc_file" + echo "export PATH=$user_bin_dir:\$PATH" >> "$USER_HOME/$rc_file" fi done + local invoking_user + invoking_user=$(get_invoking_user) + if [[ $EUID -eq 0 && -n $SUDO_USER ]]; then + echo -e "${green}Changing ownership of HeavyScript to ${blue}$invoking_user${green}...${reset}" + chown -R "$invoking_user" "$script_dir" + chown "$invoking_user" "$user_bin_dir/$script_name" + fi + echo - echo -e "${green}Successfully installed ${blue}$script_name${reset}" + echo -e "${green}Successfully installed ${blue}HeavyScript${green} to ${blue}$script_dir${reset}" + echo -e "${green}Your example cronjob:${reset}" + echo -e "${blue}bash $script_dir/heavy_script.sh update${reset}" echo } diff --git a/functions/enable/api.sh b/functions/enable/api.sh index 7875cce5..4e08bb5d 100644 --- a/functions/enable/api.sh +++ b/functions/enable/api.sh @@ -1,21 +1,32 @@ #!/bin/bash -enable_kube_api() { +manage_kube_api() { + local action="$1" local rule_comment="iX Custom Rule to drop connection requests to k8s cluster from external sources" - echo -e "${bold}Enabling Kubernetes API${reset}" + case "$action" in + enable) + echo -e "${bold}Enabling Kubernetes API${reset}" + if iptables -D INPUT -p tcp -m tcp --dport 6443 -m comment --comment "${rule_comment}" -j DROP 2> /dev/null; then + echo -e "${green}Kubernetes API enabled${reset}" + else + echo -e "${green}Kubernetes API already enabled or rule not found${reset}" + fi + ;; + disable) + echo -e "${bold}Disabling Kubernetes API${reset}" + if ! iptables -C INPUT -p tcp -m tcp --dport 6443 -m comment --comment "${rule_comment}" -j DROP 2> /dev/null; then + if iptables -A INPUT -p tcp -m tcp --dport 6443 -m comment --comment "${rule_comment}" -j DROP; then + echo -e "${green}Kubernetes API disabled${reset}" + else + echo -e "${red}Failed to add the iptables rule to disable Kubernetes API${reset}" + fi + else + echo -e "${yellow}Kubernetes API is already disabled${reset}" + fi + ;; + esac +} - local rule_exists - rule_exists=$(iptables -t filter -L INPUT 2> /dev/null | grep -q "${rule_comment}") - - if $rule_exists; then - if iptables -D INPUT -p tcp -m tcp --dport 6443 -m comment --comment "${rule_comment}" -j DROP; then - echo -e "${green}Kubernetes API enabled${reset}" - else - echo -e "${red}Kubernetes API Enable FAILED${reset}" - fi - else - echo -e "${green}Kubernetes API already enabled${reset}" - fi -} \ No newline at end of file +export -f manage_kube_api diff --git a/functions/enable/handler.sh b/functions/enable/handler.sh index 0c2fc211..4b60c6e7 100644 --- a/functions/enable/handler.sh +++ b/functions/enable/handler.sh @@ -6,7 +6,10 @@ enable_handler() { case "${args[0]}" in --api) - enable_kube_api + manage_kube_api "enable" + ;; + --disable-api) + manage_kube_api "disable" ;; --apt) toggle_apt "enable" @@ -15,7 +18,10 @@ enable_handler() { toggle_apt "disable" ;; --helm) - enable_helm + enable_helm "enable" + ;; + --disable-helm) + enable_helm "disable" ;; -h|--help) enable_help diff --git a/functions/enable/helm.sh b/functions/enable/helm.sh index 6776bd47..763b87e8 100644 --- a/functions/enable/helm.sh +++ b/functions/enable/helm.sh @@ -2,11 +2,33 @@ enable_helm() { - echo -e "${bold}Enabling Helm${reset}" - - if export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"; then - echo -e "${green}Helm Enabled${reset}" - else - echo -e "${red}Helm Enable FAILED${reset}" - fi -} \ No newline at end of file + local action="$1" + local profiles=("$HOME/.bashrc" "$HOME/.zshrc") + + for profile in "${profiles[@]}"; do + # Check if the profile file exists, create if it does not + [[ -f "$profile" ]] || touch "$profile" + + case "$action" in + enable) + echo -e "${bold}Enabling Helm in $profile${reset}" + if ! grep -q 'export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"' "$profile"; then + echo 'export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"' >> "$profile" + echo -e "${green}Helm Enabled in $profile. Please restart your shell or source your profile to apply changes.${reset}" + else + echo -e "${yellow}Helm is already enabled in $profile.${reset}" + fi + ;; + disable) + echo -e "${bold}Disabling Helm in $profile${reset}" + if grep -q 'export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"' "$profile"; then + sed -i '/export KUBECONFIG="\/etc\/rancher\/k3s\/k3s.yaml"/d' "$profile" + echo -e "${green}Helm Disabled in $profile. Please restart your shell or source your profile to apply changes.${reset}" + else + echo -e "${yellow}Helm is already disabled in $profile.${reset}" + fi + ;; + esac + done +} +export -f enable_helm \ No newline at end of file diff --git a/functions/enable/help.sh b/functions/enable/help.sh index 1e376dfb..20c27971 100644 --- a/functions/enable/help.sh +++ b/functions/enable/help.sh @@ -15,12 +15,16 @@ enable_help() { echo -e "${bold}-------${reset}" echo -e "${blue}--api${reset}" echo -e " Enables external access to the Kubernetes API server" + echo -e "${blue}--disable-api${reset}" + echo -e " Disables external access to the Kubernetes API server" echo -e "${blue}--apt${reset}" echo -e " Enable apt, apt-get, apt-key and dpkg." echo -e "${blue}--disable-apt${reset}" echo -e " Disable apt, apt-get, apt-key, and dpkg." echo -e "${blue}--helm${reset}" echo -e " Enable helm commands." + echo -e "${blue}--disable-helm${reset}" + echo -e " Disable helm commands." echo -e "${blue}-h, --help${reset}" echo -e " Show this help message and exit." echo diff --git a/functions/help.sh b/functions/help.sh index c874f3f4..ef9a7463 100644 --- a/functions/help.sh +++ b/functions/help.sh @@ -20,6 +20,7 @@ main_help(){ echo -e "${blue}heavyscript pod${reset} | Access pod logs and shells" echo -e "${blue}heavyscript pvc${reset} | Manage PVCs (mount, unmount)" echo -e "${blue}heavyscript self-update${reset} | Update HeavyScript (with or without major version update)" + echo -e "${blue}heavyscript sync${reset} | Syncs the catalog" echo -e "${blue}heavyscript update${reset} | Update applications" echo -e "${blue}heavyscript enable${reset} | Enable specific features (e.g., k3s remote node, apt)" echo diff --git a/functions/menu.sh b/functions/menu.sh deleted file mode 100644 index 2a07dc40..00000000 --- a/functions/menu.sh +++ /dev/null @@ -1,205 +0,0 @@ -#!/bin/bash - - -backup_selection(){ - while [[ $backup_selection != true ]] - do - clear -x - title - echo -e "${bold}Backup Menu${reset}" - echo -e "${bold}-----------${reset}" - echo -e "1) Create Backup" - echo -e "2) Delete Backup" - echo -e "3) Restore Backup" - echo - echo -e "0) Exit" - read -rt 120 -p "Please select an option by number: " backup_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } - case $backup_selection in - 0) - echo -e "Exiting.." - exit - ;; - 1) - read -rt 120 -p "What is the maximum number of backups you would like?: " number_of_backups || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } - if ! [[ $number_of_backups =~ ^[0-9]+$ ]]; then - echo -e "${red}Error: The input must be an interger\n${blue}\"""$number_of_backups""\"${red} is not an interger${reset}" >&2 - exit - fi - if [[ "$number_of_backups" -le 0 ]]; then - echo -e "${red}Error: Number of backups is required to be at least 1${reset}" - exit - fi - backup_selection=true - create_backup "$number_of_backups" "direct" - ;; - 2) - backup_selection=true - delete_backup - ;; - 3) - backup_selection=true - restore_backup - ;; - *) - echo -e "${red}\"$selection\" was not an option, please try again${reset}" - sleep 3 - continue - ;; - esac - done - -} - -menu_check_root() { - if [[ $EUID -ne 0 ]]; then - echo -e "${red}Error: That option requires root privileges." - echo -e "Please run the script with ${blue}sudo${red} or as ${blue}root." - echo -e "${yellow}Tip: You can re-run the last command with sudo by typing ${blue}sudo !!" - exit 1 - fi -} - -menu(){ - clear -x - title - echo -e "${bold}Available Utilities${reset}" - echo -e "${bold}-------------------${reset}" - echo -e "1) Help" - echo -e "2) Application Options" - echo -e "3) Backup Options" - echo -e "4) HeavyScript Options" - echo - echo -e "0) Exit" - read -rt 120 -p "Please select an option by number: " selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } - - - case $selection in - 0) - echo -e "Exiting.." - exit - ;; - 1) - main_help - exit - ;; - - # Applicaiton Options - 2) - menu_check_root - while [[ $misc_selection != true ]] - do - clear -x - title - echo -e "${bold}Application Options${reset}" - echo -e "${bold}-------------------${reset}" - echo -e "1) List DNS Names" - echo -e "2) Mount/Unmount PVC Storage" - echo -e "3) Open Container Shell" - echo -e "4) Open Container Logs" - echo -e "5) Start Application" - echo -e "6) Restart Application" - echo -e "7) Delete Application" - echo -e "8) Stop Application" - echo - echo -e "0) Exit" - read -rt 120 -p "Please select an option by number: " misc_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } - case $misc_selection in - 0) - echo -e "Exiting.." - exit - ;; - 1) - dns_handler - misc_selection=true - ;; - 2) - mount_prompt - misc_selection=true - ;; - 3) - container_shell_or_logs "shell" - misc_selection=true - ;; - 4) - container_shell_or_logs "logs" - misc_selection=true - ;; - 5) - start_app_prompt - misc_selection=true - ;; - 6) - restart_app_prompt - misc_selection=true - ;; - 7) - delete_app_prompt - misc_selection=true - ;; - 8) - stop_app_prompt - misc_selection=true - ;; - *) - echo -e "${red}\"$selection\" was not an option, please try again${reset}" - sleep 3 - continue - ;; - esac - done - ;; - # Backup Options - 3) - menu_check_root - backup_selection - ;; - - # HeavyScript Options - 4) - while [[ $misc_selection != true ]] - do - clear -x - title - echo -e "${bold}HeavyScript Options Menu${reset}" - echo -e "${bold}------------------------${reset}" - echo -e "1) Self Update" - echo -e "2) Choose Branch" - echo -e "3) Add Script to Global Path" - echo -e "${gray}This will download the one liner, and add it to your global path, you only need to do this once.${reset} " - echo - echo -e "0) Exit" - read -rt 120 -p "Please select an option by number: " misc_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } - case $misc_selection in - 0) - echo -e "Exiting.." - exit - ;; - 1) - misc_selection=true - self_update - ;; - 2) - misc_selection=true - choose_branch - ;; - 3) - misc_selection=true - add_script_to_global_path - ;; - *) - echo -e "${blue}\"$selection\"${red} was not an option, please try again${reset}" - sleep 3 - continue - ;; - esac - done - ;; - *) - echo -e "${blue}\"$selection\"${red} was not an option, please try again${reset}" - sleep 3 - menu - ;; - esac - echo -} -export -f menu diff --git a/functions/menu/application_selection.sh b/functions/menu/application_selection.sh new file mode 100644 index 00000000..a07d66c6 --- /dev/null +++ b/functions/menu/application_selection.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +application_menu() { + local misc_selection="" + while true; do + clear -x + title + echo -e "${bold}Application Options${reset}" + echo -e "${bold}-------------------${reset}" + echo -e "1) List DNS Names" + echo -e "2) Mount/Unmount PVC Storage" + echo -e "3) Open Container Shell" + echo -e "4) Open Container Logs" + echo -e "5) Start Application" + echo -e "6) Restart Application" + echo -e "7) Delete Application" + echo -e "8) Stop Application" + echo + echo -e "9) Back to Main Menu" + echo -e "0) Exit" + read -rt 120 -p "Please select an option by number: " misc_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + + case $misc_selection in + 0) + echo -e "Exiting.." + exit + ;; + 1) + dns_handler + exit + ;; + 2) + mount_prompt + exit + ;; + 3) + container_shell_or_logs "shell" + exit + ;; + 4) + container_shell_or_logs "logs" + exit + ;; + 5) + start_app_prompt + exit + ;; + 6) + restart_app_prompt + exit + ;; + 7) + delete_app_prompt + exit + ;; + 8) + stop_app_prompt + exit + ;; + 9) + # Break the loop to go back to the main menu + break + ;; + *) + echo -e "${red}\"$misc_selection\" was not an option, please try again${reset}" + sleep 3 + ;; + esac + done +} diff --git a/functions/menu/backup_selection.sh b/functions/menu/backup_selection.sh new file mode 100644 index 00000000..9ef1b8e0 --- /dev/null +++ b/functions/menu/backup_selection.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +backup_selection() { + local backup_selection="" + while true; do + clear -x + title + echo -e "${bold}Backup Menu${reset}" + echo -e "${bold}-----------${reset}" + echo -e "1) Create Backup" + echo -e "2) Delete Backup" + echo -e "3) Restore Backup" + echo -e "4) Install/Update Velero" + echo + echo -e "9) Back to Main Menu" + echo -e "0) Exit" + read -rt 120 -p "Please select an option by number: " backup_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + + case $backup_selection in + 0) + echo -e "Exiting.." + exit + ;; + 1) + read -rt 120 -p "What is the maximum number of backups you would like?: " number_of_backups || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + if ! [[ $number_of_backups =~ ^[0-9]+$ ]]; then + echo -e "${red}Error: The input must be an interger\n${blue}\"$number_of_backups\"${red} is not an integer${reset}" >&2 + exit + fi + if [[ "$number_of_backups" -le 0 ]]; then + echo -e "${red}Error: Number of backups is required to be at least 1${reset}" + exit + fi + create_backup "$number_of_backups" "direct" + exit + ;; + 2) + delete_backup + exit + ;; + 3) + restore_backup + exit + ;; + 4) + velero_check + exit + ;; + 9) + # Break the loop to go back to the main menu + break + ;; + *) + echo -e "${red}\"$backup_selection\" was not an option, please try again${reset}" + sleep 3 + ;; + esac + done +} diff --git a/functions/menu/heavyscript_menu.sh b/functions/menu/heavyscript_menu.sh new file mode 100644 index 00000000..24b7a768 --- /dev/null +++ b/functions/menu/heavyscript_menu.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +heavyscript_menu() { + local misc_selection="" + while true; do + clear -x + title + echo -e "${bold}HeavyScript Options Menu${reset}" + echo -e "${bold}------------------------${reset}" + echo -e "1) Self Update" + echo -e "2) Choose Branch" + echo -e "3) Add Script to Global Path" + echo -e "${gray}This will download the one liner, and add it to your global path, you only need to do this once.${reset}" + echo + echo -e "9) Back to Main Menu" + echo -e "0) Exit" + read -rt 120 -p "Please select an option by number: " misc_selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + + case $misc_selection in + 0) + echo -e "Exiting.." + exit + ;; + 1) + self_update + exit + ;; + 2) + choose_branch + exit + ;; + 3) + add_script_to_global_path + exit + ;; + 9) + # Break the loop to go back to the main menu + break + ;; + *) + echo -e "${blue}\"$misc_selection\"${red} was not an option, please try again${reset}" + sleep 3 + ;; + esac + done +} diff --git a/functions/menu/menu.sh b/functions/menu/menu.sh new file mode 100644 index 00000000..355124c5 --- /dev/null +++ b/functions/menu/menu.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +menu_check_root() { + if [[ $EUID -ne 0 ]]; then + echo -e "${red}Error: That option requires root privileges." + echo -e "Please run the script with ${blue}sudo${red} or as ${blue}root." + echo -e "${yellow}Tip: You can re-run the last command with sudo by typing ${blue}sudo !!" + exit 1 + fi +} + +menu() { + while true; do + clear -x + title + echo -e "${bold}Available Utilities${reset}" + echo -e "${bold}-------------------${reset}" + echo -e "1) Help" + echo -e "2) Application Options" + echo -e "3) Backup Options" + echo -e "4) HeavyScript Options" + echo + echo -e "0) Exit" + read -rt 120 -p "Please select an option by number: " selection || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + + case $selection in + 0) + echo -e "Exiting.." + exit + ;; + 1) + main_help + exit + ;; + 2) # Application Options + menu_check_root + application_menu + ;; + 3) # Backup Options + menu_check_root + backup_selection + ;; + 4) # HeavyScript Options + heavyscript_menu + ;; + *) + echo -e "${blue}\"$selection\"${red} was not an option, please try again${reset}" + sleep 3 + ;; + esac + done +} +export -f menu diff --git a/functions/menu/velero.sh b/functions/menu/velero.sh new file mode 100644 index 00000000..d0d5ea8d --- /dev/null +++ b/functions/menu/velero.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +get_user_home() { + local user_home + + if [[ $EUID -eq 0 ]]; then # Script is running as root + # Use SUDO_USER if set, otherwise fall back to root's home + user_home=$(getent passwd "${SUDO_USER:-root}" | cut -d: -f6) + else # Script is run by a regular user + user_home=$HOME + fi + + echo "$user_home" +} + +USER_HOME=$(get_user_home) + +velero_symlink() { + local context="$1" # Context of the symlink creation (install, update, or check) + + ln -sf "$USER_HOME/bin/velero" /usr/local/bin/velero + case "$context" in + "install") + echo -e "${green}Symlink created in ${blue}/usr/local/bin${green} for the first time.${reset}" + ;; + "update") + echo -e "${green}Symlink in ${blue}/usr/local/bin${green} updated.${reset}" + ;; + "check") + echo -e "${yellow}Symlink in ${blue}/usr/local/bin${yellow} verified and recreated if necessary.${reset}" + ;; + esac +} + +# Function to get the latest Velero release URL +velero_latest_release_url() { + wget -qO- "https://api.github.com/repos/vmware-tanzu/velero/releases/latest" | jq -r '.assets[] | select(.name | contains("linux-amd64")).browser_download_url' +} + +# Function to install Velero +velero_install() { + local release_url + release_url=$(velero_latest_release_url) + wget -qO velero.tar.gz "$release_url" + mkdir -p "$USER_HOME/bin/velero_real" + tar -xzf velero.tar.gz -C "$USER_HOME/bin/velero_real" + + # Find and move the Velero binary to the velero_real directory + local velero_dir + velero_dir=$(find "$USER_HOME/bin/velero_real" -type d -name "velero-*" -print -quit) + if [[ -d "$velero_dir" ]]; then + mv "$velero_dir/velero" "$USER_HOME/bin/velero_real/velero" + rm -rf "$velero_dir" + fi + + # Create or update the wrapper script + cat > "$USER_HOME/bin/velero" << EOF +#!/bin/bash +# Wrapper script for Velero +if [[ \$1 == "install" ]]; then + echo "'velero install' is not allowed. Please use the application instead..." +else + "$USER_HOME/bin/velero_real/velero" "\$@" +fi +EOF + chmod +x "$USER_HOME/bin/velero_real/velero" + chmod +x "$USER_HOME/bin/velero" + rm velero.tar.gz + ln -sf "$USER_HOME/bin/velero" /usr/local/bin/velero + echo -e "${green}Velero installed successfully.${reset}" +} + +# Function to check Velero installation and decide action +velero_check() { + if command -v velero &> /dev/null; then + local current_version + local latest_version + latest_version=$(wget -qO- "https://api.github.com/repos/vmware-tanzu/velero/releases/latest" | jq -r '.tag_name') + current_version=$(velero version --client-only | grep Version | cut -d ':' -f 2 | xargs) + + if [ "$current_version" != "$latest_version" ]; then + echo -e "${green}Updating Velero to the latest version.${reset}" + velero_install + # Recreate the symlink after updating + velero_symlink "update" + else + echo -e "${green}Velero is up to date.${reset}" + # Check and recreate the symlink if needed + velero_symlink "check" + fi + else + echo -e "${yellow}Velero is not installed. Installing now.${reset}" + velero_install + # Create the symlink for the first time + velero_symlink "install" + fi +} \ No newline at end of file diff --git a/functions/pod/container_shell_or_logs.sh b/functions/pod/container_shell_or_logs.sh index 894eb922..77f8c2bf 100644 --- a/functions/pod/container_shell_or_logs.sh +++ b/functions/pod/container_shell_or_logs.sh @@ -172,15 +172,18 @@ cmd_execute_shell() { } export -f cmd_execute_shell - - cmd_execute_logs() { - local lines - while true - do + local lines=500 # Default to 500 lines + while true; do cmd_print_app_pod_container echo - read -rt 120 -p "How many lines of logs do you want to display?(\"-1\" for all): " lines || { echo -e "${red}\nFailed to make a selection in time${reset}" ; exit; } + read -rt 120 -p "How many lines of logs do you want to display? (Default is 500, \"-1\" for all): " lines_input || { + echo -e "${red}\nFailed to make a selection in time${reset}" ; + exit; + } + + [[ -z "$lines_input" ]] || lines=$lines_input + if ! [[ $lines =~ ^[0-9]+$|^-1$ ]]; then echo -e "${red}Error: ${blue}\"$lines\"${red} was not a number.. Try again${reset}" sleep 3