Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions logging_utils.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#!/bin/bash
# Shared logging utilities for kagglelink scripts
#
# This library provides consistent logging functions with emojis,
# timestamps, and error categorization for all kagglelink scripts.
#
# Usage:
# source logging_utils.sh
# log_info "Starting operation..."
# log_success "Operation completed"
# log_error "Something went wrong"

# Store step start times for elapsed time calculation
declare -A _STEP_START_TIMES

# Log an informational message with ⏳ emoji and timestamp
# Args:
# $1: Message to log
# Output: Formatted message to stdout
log_info() {
echo "⏳ [$(date +%H:%M:%S)] $1"
}

# Log a success message with ✅ emoji and timestamp
# Args:
# $1: Message to log
# Output: Formatted message to stdout
log_success() {
echo "✅ [$(date +%H:%M:%S)] $1"
}

# Log an error message with ❌ emoji and timestamp to stderr
# Args:
# $1: Message to log
# Output: Formatted error message to stderr
log_error() {
echo "❌ [$(date +%H:%M:%S)] ERROR: $1" >&2
}

# Start tracking a step for elapsed time calculation
# Args:
# $1: Step name
# Output: Informational log message
log_step_start() {
local step_name="$1"
_STEP_START_TIMES["$step_name"]=$(date +%s)
log_info "$step_name..."
}

# Complete a step and display elapsed time
# Args:
# $1: Step name
# Output: Success message with elapsed time
log_step_complete() {
local step_name="$1"
local start_time="${_STEP_START_TIMES[$step_name]}"
if [ -n "$start_time" ]; then
local elapsed=$(($(date +%s) - start_time))
log_success "$step_name completed (${elapsed}s)"
else
log_success "$step_name completed"
fi
}

# Categorize and display error with contextual guidance
# Args:
# $1: Error type (prerequisite, network, upstream)
# $2: Error message
# $3: Suggested action
# Output: Formatted error with category-specific emoji and guidance to stderr
categorize_error() {
local error_type="$1"
local message="$2"
local suggestion="$3"

case "$error_type" in
"prerequisite")
log_error "$message"
echo " 💡 Action required: $suggestion" >&2
;;
"network")
log_error "$message"
echo " 🌐 Check connectivity: $suggestion" >&2
;;
"upstream")
log_error "$message"
echo " 🔧 Upstream issue: $suggestion" >&2
;;
*)
log_error "$message"
;;
esac
}

# Display success banner with Zrok share token and connection instructions
# Args:
# $1: Zrok share token
# Output: Formatted success banner to stdout
show_success_banner() {
local share_token="$1"

if command -v gum &>/dev/null; then
local header
header=$(gum style --foreground 212 --border double --border-foreground 212 --padding "1 2" --align center --width 60 "✅ Setup Complete!")
local message
message=$(gum style --foreground 255 --align center --width 60 "Your Kaggle instance is ready for remote access!")

local token_label
token_label=$(gum style --foreground 99 "📡 Zrok Share Token:")
local token_value
token_value=$(gum style --foreground 212 --bold "$share_token")
local token_section
token_section=$(gum join --vertical --align center "$token_label" "$token_value")
local token_box
token_box=$(gum style --border rounded --padding "1 2" --border-foreground 99 --width 60 --align center "$token_section")

local instr_label
instr_label=$(gum style --foreground 255 "🖥️ On your LOCAL machine, run:")
local cmd1
cmd1=$(gum style --foreground 212 "zrok access private $share_token")
local cmd2_label
cmd2_label=$(gum style --foreground 255 "Then connect via SSH:")
local cmd2
cmd2=$(gum style --foreground 212 "ssh -p 9191 root@127.0.0.1")

local cmds_content
cmds_content=$(gum join --vertical --align center "$instr_label" " " "$cmd1" " " "$cmd2_label" " " "$cmd2")
local cmds_box
cmds_box=$(gum style --border rounded --padding "1 2" --border-foreground 255 --width 60 --align center "$cmds_content")

printf "\n"
gum join --vertical --align center "$header" " " "$message" " " "$token_box" " " "$cmds_box"
else
echo ""
echo "╔════════════════════════════════════════════════════════════════╗"
echo "║ ✅ Setup Complete! ║"
echo "╠════════════════════════════════════════════════════════════════╣"
echo "║ ║"
echo "║ Your Kaggle instance is ready for remote access! ║"
echo "║ ║"
echo "║ 📡 Zrok Share Token: $share_token"
echo "║ ║"
echo "║ 🖥️ On your LOCAL machine, run: ║"
echo "║ ║"
echo "║ zrok access private $share_token"
echo "║ ║"
echo "║ Then connect via SSH: ║"
echo "║ ║"
echo "║ ssh -p 9191 root@127.0.0.1 ║"
echo "║ ║"
echo "╚════════════════════════════════════════════════════════════════╝"
echo ""
fi
}
107 changes: 78 additions & 29 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,84 @@

set -e

# ============================================================================
# Inline Logging Functions (embedded for bootstrap phase)
# ============================================================================
# These are embedded directly in setup.sh because this script is downloaded
# standalone before the repository is cloned. Other scripts (setup_kaggle_zrok.sh,
# start_zrok.sh) source logging_utils.sh from the cloned repository.

# Store step start times for elapsed time calculation
declare -A _STEP_START_TIMES

log_info() {
echo "⏳ [$(date +%H:%M:%S)] $1"
}

log_success() {
echo "✅ [$(date +%H:%M:%S)] $1"
}

log_error() {
echo "❌ [$(date +%H:%M:%S)] ERROR: $1" >&2
}

log_step_start() {
local step_name="$1"
_STEP_START_TIMES["$step_name"]=$(date +%s)
log_info "$step_name..."
}

log_step_complete() {
local step_name="$1"
local start_time="${_STEP_START_TIMES[$step_name]}"
if [ -n "$start_time" ]; then
local elapsed=$(($(date +%s) - start_time))
log_success "$step_name completed (${elapsed}s)"
else
log_success "$step_name completed"
fi
}

categorize_error() {
local error_type="$1"
local message="$2"
local suggestion="$3"

case "$error_type" in
"prerequisite")
log_error "$message"
echo " 💡 Action required: $suggestion" >&2
;;
"network")
log_error "$message"
echo " 🌐 Check connectivity: $suggestion" >&2
;;
"upstream")
log_error "$message"
echo " 🔧 Upstream issue: $suggestion" >&2
;;
*)
log_error "$message"
;;
esac
}
# ============================================================================

# Version and branch configuration
KAGGLELINK_VERSION="1.1.0"
KAGGLELINK_BRANCH="${BRANCH:-main}"

# Security: Validate KAGGLELINK_BRANCH to prevent argument injection
# Branch names must not start with '-' to prevent git argument injection
if [[ "$KAGGLELINK_BRANCH" =~ ^- ]]; then
echo "❌ Error: Invalid branch name '$KAGGLELINK_BRANCH'"
echo " Branch names cannot start with '-' (security: prevents argument injection)"
categorize_error "prerequisite" "Invalid branch name '$KAGGLELINK_BRANCH'" "Branch names cannot start with '-' (security: prevents argument injection)"
exit 1
fi

# Reliability: Check for git installation
if ! command -v git &> /dev/null; then
echo "❌ Error: git is not installed"
echo " Please install git and try again"
echo " - Debian/Ubuntu: sudo apt-get install git"
echo " - RHEL/CentOS: sudo yum install git"
echo " - macOS: brew install git"
categorize_error "prerequisite" "git is not installed" "Install git: apt-get install git (Debian/Ubuntu), yum install git (RHEL/CentOS), or brew install git (macOS)"
exit 1
fi

Expand Down Expand Up @@ -117,45 +176,35 @@ fi

# Validate that AUTH_KEYS_URL uses HTTPS (security requirement)
if [[ ! "$AUTH_KEYS_URL" =~ ^https:// ]]; then
echo "❌ Error: Keys URL must use HTTPS (not HTTP)"
echo " Insecure URL: $AUTH_KEYS_URL"
categorize_error "prerequisite" "Keys URL must use HTTPS (not HTTP): $AUTH_KEYS_URL" "Use HTTPS URL instead"
if [[ "$AUTH_KEYS_URL" =~ ^http:// ]]; then
echo " Use: ${AUTH_KEYS_URL/http:/https:}"
else
echo " URL must start with https://"
echo " Suggested: ${AUTH_KEYS_URL/http:/https:}" >&2
fi
exit 1
fi

echo "⏳ Cloning repository..."
log_step_start "Cloning repository"
if [ -d "$INSTALL_DIR" ]; then
echo "Repository directory already exists. Removing it..."
log_info "Repository directory already exists. Removing it..."
rm -rf "$INSTALL_DIR"
fi

if ! git clone -b "$KAGGLELINK_BRANCH" "$REPO_URL" "$INSTALL_DIR"; then
echo "❌ Error: Failed to clone branch '$KAGGLELINK_BRANCH'"
echo " Possible reasons:"
echo " - Branch does not exist"
echo " - Network connectivity issues"
echo " - GitHub is unreachable"
categorize_error "network" "Failed to clone branch '$KAGGLELINK_BRANCH'" "Check branch exists and network connectivity"
exit 1
fi
echo "✅ Cloned repository (branch: ${KAGGLELINK_BRANCH})"
log_step_complete "Cloning repository"

echo "⏳ Changing to repository directory..."
log_info "Changing to repository directory..."
cd "$INSTALL_DIR"

echo "⏳ Making scripts executable..."
log_info "Making scripts executable..."
chmod +x setup_kaggle_zrok.sh start_zrok.sh

echo "⏳ Setting up SSH with your public keys..."
log_step_start "Setting up SSH with your public keys"
./setup_kaggle_zrok.sh "$AUTH_KEYS_URL"
log_step_complete "Setting up SSH with your public keys"

echo "⏳ Starting zrok service with your token..."
log_info "Starting zrok service with your token..."
# Note: start_zrok.sh is a blocking process that will display success banner
./start_zrok.sh "$ZROK_TOKEN"

echo "✅ Setup complete!"
echo "✅ You should now be able to connect to your Kaggle instance via SSH."
echo "✅ If you see a URL above, use that to connect from your local machine."
echo "✅ For more information, visit: https://github.com/bhdai/kagglelink"
Loading