freeleaps-pub/devbox/devbox.local/devbox
2025-02-11 16:54:13 +08:00

3282 lines
104 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Modifying it manually is not recommended
# :wrapper.bash3_bouncer
if [[ "${BASH_VERSINFO:-0}" -lt 3 ]]; then
printf "bash version 3 or higher is required\n" >&2
exit 1
fi
# :command.master_script
# :command.version_command
version_command() {
echo "$version"
}
upper() {
echo "$1" | tr '[:lower:]' '[:upper:]'
}
lower() {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
# Add a key-value pair to the args array
add_arg() {
local key="$1"
local value="$2"
args_keys+=("$key")
args_values+=("$value")
}
# Get the value of a key from the args array
get_arg() {
local key="$1"
local default="${2:-}"
local i
for i in "${!args_keys[@]}"; do
if [ "${args_keys[$i]}" = "$key" ]; then
echo "${args_values[$i]}"
return 0
fi
done
echo "$default"
return 1
}
# :command.usage
devbox_usage() {
printf "devbox - DevBox Command Line Tool\n\n"
printf "%s\n" "Usage:"
printf " devbox COMMAND\n"
printf " devbox [COMMAND] --help | -h\n"
printf " devbox --version | -v\n"
echo
# :command.usage_commands
printf "%s\n" "Commands:"
printf " %s Initialize the local development environment based on DevBox container.\n" "init"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
printf " %s\n" "--version, -v"
printf " Show version number\n"
echo
# :command.usage_environment_variables
printf "%s\n" "Environment Variables:"
# :environment_variable.usage
printf " %s\n" "FREELEAPS_USERNAME"
printf " Set the Freeleaps username for cloning the source repository.\n"
echo
# :environment_variable.usage
printf " %s\n" "FREELEAPS_PASSWORD"
printf " Set the Freeleaps password for cloning the source repository.\n"
echo
# :environment_variable.usage
printf " %s\n" "WORKING_HOME"
printf " Set the working home directory for DevBox.\n"
echo
fi
}
# :command.usage
devbox_init_usage() {
if [[ -n $long_usage ]]; then
printf "devbox init\n\n"
printf " Initialize the local development environment based on DevBox container.\n This command will pull the DevBox container image, create containers for \n various Freeleaps components, clone the source code repository, and \n persist relevant container/process information under WORKING_HOME.\n \n Sub-command \`init\` uses Docker (or another container runtime) to set \n up a local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Validate flags and environment.\n 2. Pull DevBox base image and create container.\n 3. Pull each required component image, create containers.\n 4. Clone remote source repository using FREELEAPS_USERNAME/PASSWORD.\n 5. Start back-end and front-end services.\n 6. Persist container IDs, logs, etc. into WORKING_HOME.\n\n"
else
printf "devbox init - Initialize the local development environment based on DevBox container.\n\n"
fi
printf "Alias: i\n"
echo
printf "%s\n" "Usage:"
printf " devbox init [OPTIONS]\n"
printf " devbox init --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_flags
# :flag.usage os (auto, linux, darwin, wsl2)
printf " %s\n" "--os OS"
printf " Specifies the operating system (auto, linux, darwin, wsl2). Default is auto.\n"
printf " %s\n" "Default: auto"
echo
# :flag.usage arch
printf " %s\n" "--arch ARCH"
printf " Specifies the architecture (auto, amd64, arm64). Default is auto.\n"
printf " %s\n" "Default: auto"
echo
# :flag.usage devbox container name
printf " %s\n" "--devbox-container-name DEVBOX_CONTAINER_NAME"
printf " Specifies the DevBox container name. Default is devbox.\n"
printf " %s\n" "Default: devbox"
echo
# :flag.usage devbox container port
printf " %s\n" "--devbox-container-port DEVBOX_CONTAINER_PORT"
printf " Specifies the container port for DevBox SSH access. Default is 22222.\n"
printf " %s\n" "Default: 22222"
echo
# :flag.usage devbox image repo
printf " %s\n" "--devbox-image-repo DEVBOX_IMAGE_REPO"
printf " Specifies the DevBox container image repository. Default is\n docker.io/freeleaps.\n"
printf " %s\n" "Default: docker.io/freeleaps"
echo
# :flag.usage devbox frontend port
printf " %s\n" "--devbox-frontend-port DEVBOX_FRONTEND_PORT"
printf " Specifies the container port for DevBox frontend access. Default is 5173.\n"
printf " %s\n" "Default: 5173"
echo
# :flag.usage devbox backend port
printf " %s\n" "--devbox-backend-port DEVBOX_BACKEND_PORT"
printf " Specifies the container port for DevBox backend access. Default is 8002.\n"
printf " %s\n" "Default: 8002"
echo
# :flag.usage devbox image name
printf " %s\n" "--devbox-image-name DEVBOX_IMAGE_NAME"
printf " Specifies the DevBox container image name. Default is devbox.\n"
printf " %s\n" "Default: devbox"
echo
# :flag.usage devbox image tag
printf " %s\n" "--devbox-image-tag DEVBOX_IMAGE_TAG"
printf " Specifies the DevBox container image tag. Default is latest.\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage working home
printf " %s\n" "--working-home WORKING_HOME"
printf " Specifies the working home of DevBox CLI. Default is ${HOME}/.devbox.\n"
echo
# :flag.usage freeleaps username
printf " %s\n" "--freeleaps-username FREELEAPS_USERNAME (required)"
printf " Specifies the Freeleaps.com repository username (Required).\n"
echo
# :flag.usage freeleaps password
printf " %s\n" "--freeleaps-password FREELEAPS_PASSWORD (required)"
printf " Specifies the Freeleaps.com password repository (Required).\n"
echo
# :flag.usage use local component
printf " %s\n" "--use-local-component USE_LOCAL_COMPONENT"
printf " Check if use local component or use online dev environment. (Default: false, use online service) (Optional)\n"
echo
# :flag.usage devsvc image repo
printf " %s\n" "--devsvc-image-repo DEVSVC_IMAGE_REPO"
printf " Specifies the repository for devsvc component. (Optional)\n"
echo
# :flag.usage devsvc image name
printf " %s\n" "--devsvc-image-name DEVSVC_IMAGE_NAME"
printf " Specifies the image name for devsvc component. (Optional)\n"
echo
# :flag.usage devsvc image tag
printf " %s\n" "--devsvc-image-tag DEVSVC_IMAGE_TAG"
printf " Specifies the image tag for devsvc component. (Optional, default=latest-)\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage notification, image repo
printf " %s\n" "--notification-image-repo NOTIFICATION_IMAGE_REPO"
printf " Specifies the repository for notification component. (Optional)\n"
echo
# :flag.usage notification image name
printf " %s\n" "--notification-image-name NOTIFICATION_IMAGE_NAME"
printf " Specifies the image name for notification component. (Optional)\n"
echo
# :flag.usage notification image tag
printf " %s\n" "--notification-image-tag NOTIFICATION_IMAGE_TAG"
printf " Specifies the image tag for notification component. (Optional, default=latest)\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage content image repo
printf " %s\n" "--content-image-repo CONTENT_IMAGE_REPO"
printf " Specifies the repository for content component. (Optional)\n"
echo
# :flag.usage content image name
printf " %s\n" "--content-image-name CONTENT_IMAGE_NAME"
printf " Specifies the image name for content component. (Optional)\n"
echo
# :flag.usage content image tag
printf " %s\n" "--content-image-tag CONTENT_IMAGE_TAG"
printf " Specifies the image tag for content component. (Optional, default=latest)\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage central storage image repo
printf " %s\n" "--central_storage-image-repo CENTRAL_STORAGE_IMAGE_REPO"
printf " Specifies the repository for central_storage component. (Optional)\n"
echo
# :flag.usage central storage image name
printf " %s\n" "--central_storage-image-name CENTRAL_STORAGE_IMAGE_NAME"
printf " Specifies the image name for central_storage component. (Optional)\n"
echo
# :flag.usage central storage image tag
printf " %s\n" "--central_storage-image-tag CENTRAL_STORAGE_IMAGE_TAG"
printf " Specifies the image tag for central_storage component. (Optional, default=latest)\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage authentication image repo
printf " %s\n" "--authentication-image-repo AUTHENTICATION_IMAGE_REPO"
printf " Specifies the repository for authentication component. (Optional)\n"
echo
# :flag.usage authentication image name
printf " %s\n" "--authentication-image-name AUTHENTICATION_IMAGE_NAME"
printf " Specifies the image name for authentication component. (Optional)\n"
echo
# :flag.usage authentication image tag
printf " %s\n" "--authentication-image-tag AUTHENTICATION_IMAGE_TAG"
printf " Specifies the image tag for authentication component. (Optional, default=latest)\n"
printf " %s\n" "Default: latest"
echo
# :flag.usage force
printf " %s\n" "--force, -f"
printf " Force initialization even if resources already exist.\n"
echo
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox init --os=linux --arch=arm64 --freeleaps-username alice\n --freeleaps-password secret\n"
printf " devbox init \ --devbox-container-name custom-devbox \ --devbox-container-port\n 22222 \ --freeleaps-username alice \ --freeleaps-password secret\n"
echo
fi
}
# :command.usage
devbox_deinit_usage() {
if [[ -n $long_usage ]]; then
printf "devbox deinit\n\n"
printf " De-initialize the local development environment based on DevBox container.\n This command will stop and remove all containers, clean up the working \n directory, and reset the environment to the initial state.\n \n Sub-command \`deinit\` uses Docker (or another container runtime) to clean \n up the local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Stop and remove all containers.\n 2. Clean up the working directory.\n 3. Reset the environment to the initial state.\n\n"
else
printf "devbox deinit - De-initialize the local development environment based on DevBox container.\n\n"
fi
printf "Alias: d\n"
echo
printf "%s\n" "Usage:"
printf " devbox deinit [OPTIONS]\n"
printf " devbox deinit --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_flags
# :flag.usage
printf " %s\n" "--working-home WORKING_HOME"
printf " Specifies the working home of DevBox CLI. Default is ${HOME}/.devbox.\n"
printf " %s\n" "Default: ${HOME}/.devbox"
echo
# :flag.usage
printf " %s\n" "--clear-logs CLEAR_LOGS"
printf " Specifies whether clear log files or not. Default is true.\n"
printf " %s\n" "Default: true"
echo
# :flag.usage
printf " %s\n" "--clear-repo CLEAR_REPO"
printf " Specifies whether delete source repository or not. Default is false.\n"
printf " %s\n" "Default: false"
echo
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox deinit\n"
printf " devbox deinit --working-home=/tmp/devbox --clear-logs=false --clear-repo=true\n"
echo
fi
}
# :command.usage
devbox_start_usage() {
if [[ -n $long_usage ]]; then
printf "devbox start\n\n"
printf " Start the local development environment based on DevBox container.\n This command will start all containers, services, and processes that \n are required for Freeleaps development.\n \n Sub-command \`start\` uses Docker (or another container runtime) to start \n the local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Start all containers.\n 2. Start all services and processes.\n\n"
else
printf "devbox start - Start the local development environment based on DevBox container.\n\n"
fi
printf "Alias: s\n"
echo
printf "%s\n" "Usage:"
printf " devbox start [OPTIONS]\n"
printf " devbox start --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_flags
# :flag.usage
printf " %s\n" "--component COMPONENT"
printf " Specifies the name of the component to start (e.g., mongodb, rabbitmq,\n backend, frontend, devsvc, content, central_storage,\n authentication).\n"
echo
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox start\n"
printf " devbox start --component=backend\n"
echo
fi
}
# :command.usage
devbox_stop_usage() {
if [[ -n $long_usage ]]; then
printf "devbox stop\n\n"
printf " Stop the local development environment based on DevBox container.\n This command will stop all containers, services, and processes that \n are required for Freeleaps development.\n \n Sub-command \`stop\` uses Docker (or another container runtime) to stop \n the local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Stop all containers.\n 2. Stop all services and processes.\n\n"
else
printf "devbox stop - Stop the local development environment based on DevBox container.\n\n"
fi
printf "Alias: p\n"
echo
printf "%s\n" "Usage:"
printf " devbox stop [OPTIONS]\n"
printf " devbox stop --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_flags
# :flag.usage
printf " %s\n" "--component COMPONENT"
printf " Specifies the name of the component to stop (e.g., mongodb, rabbitmq,\n backend, frontend, devsvc, content, central_storage,\n authentication).\n"
echo
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox stop\n"
printf " devbox stop --component=backend\n"
echo
fi
}
# :command.usage
devbox_status_usage() {
if [[ -n $long_usage ]]; then
printf "devbox status\n\n"
printf " Display the status of the local development environment based on DevBox\n container.\n This command will show the status of all containers, services, and processes \n that are required for Freeleaps development.\n \n Sub-command \`status\` uses Docker (or another container runtime) to show \n the status of the local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Show the status of all containers.\n 2. Show the status of all services and processes.\n\n"
else
printf "devbox status - Display the status of the local development environment based on DevBox container.\n\n"
fi
printf "Alias: t\n"
echo
printf "%s\n" "Usage:"
printf " devbox status\n"
printf " devbox status --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox status\n"
printf " devbox status --component=backend\n"
echo
fi
}
# :command.usage
devbox_restart_usage() {
if [[ -n $long_usage ]]; then
printf "devbox restart\n\n"
printf " Restart the local development environment based on DevBox container.\n This command will restart all containers, services, and processes that \n are required for Freeleaps development.\n \n Sub-command \`restart\` uses Docker (or another container runtime) to restart \n the local DevBox environment for Freeleaps development. \n It follows these major steps:\n 1. Stop all containers.\n 2. Start all containers.\n 3. Stop all services and processes.\n 4. Start all services and processes.\n\n"
else
printf "devbox restart - Restart the local development environment based on DevBox container.\n\n"
fi
printf "Alias: r\n"
echo
printf "%s\n" "Usage:"
printf " devbox restart\n"
printf " devbox restart --help | -h\n"
echo
# :command.long_usage
if [[ -n "$long_usage" ]]; then
printf "%s\n" "Options:"
# :command.usage_fixed_flags
printf " %s\n" "--help, -h"
printf " Show this help\n"
echo
# :command.usage_examples
printf "%s\n" "Examples:"
printf " devbox restart\n"
printf " devbox restart --component=backend\n"
echo
fi
}
# :command.normalize_input
# :command.normalize_input_function
normalize_input() {
local arg passthru flags
passthru=false
while [[ $# -gt 0 ]]; do
arg="$1"
if [[ $passthru == true ]]; then
input+=("$arg")
elif [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then
input+=("${BASH_REMATCH[1]}")
input+=("${BASH_REMATCH[2]}")
elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then
input+=("${BASH_REMATCH[1]}")
input+=("${BASH_REMATCH[2]}")
elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then
flags="${BASH_REMATCH[1]}"
for ((i = 0; i < ${#flags}; i++)); do
input+=("-${flags:i:1}")
done
elif [[ "$arg" == "--" ]]; then
passthru=true
input+=("$arg")
else
input+=("$arg")
fi
shift
done
}
# :command.inspect_args
inspect_args() {
# Check and output the simulated args associative array (using args_keys and args_values)
if [ ${#args_keys[@]} -gt 0 ]; then
# 利用 printf 和 sort 对键进行排序
sorted_keys=$(printf "%s\n" "${args_keys[@]}" | sort)
echo "args:"
for key in $sorted_keys; do
value=""
# Find the value based on the key
for i in `seq 0 $((${#args_keys[@]} - 1))`; do
if [ "${args_keys[$i]}" = "$key" ]; then
value="${args_values[$i]}"
break
fi
done
done
else
echo "args: none"
fi
# Check and output the simulated deps associative array (using deps_keys and deps_values)
if [ ${#deps_keys[@]} -gt 0 ]; then
sorted_keys=$(printf "%s\n" "${deps_keys[@]}" | sort)
echo
echo "deps:"
for key in $sorted_keys; do
value=""
for i in `seq 0 $((${#deps_keys[@]} - 1))`; do
if [ "${deps_keys[$i]}" = "$key" ]; then
value="${deps_values[$i]}"
break
fi
done
echo "- \$deps[$key] = $value"
done
fi
# Check and output the simulated env_vars associative array (using env_var_names)
if [ ${#env_var_names[@]} -gt 0 ]; then
sorted_names=$(printf "%s\n" "${env_var_names[@]}" | sort)
echo
echo "environment variables:"
for name in $sorted_names; do
# Look up the value based on the name
echo "- \$${name} = ${!name:-}"
done
fi
}
install_docker() {
echo "[INFO] Checking Docker installation..."
# Check if Docker CLI is installed
if ! command -v docker >/dev/null 2>&1; then
echo "[ERROR] Docker CLI is not installed."
return 1
fi
echo "[INFO] Docker CLI is installed. Checking daemon..."
# Check if Docker daemon is running
if docker info >/dev/null 2>&1; then
echo "[OK] Docker daemon is running."
return 0
fi
# Check if running on WSL
if grep -qi microsoft /proc/version; then
echo "[INFO] Detected WSL environment. Skipping service startup."
if [ -S /var/run/docker.sock ]; then
echo "[OK] Docker socket found (/var/run/docker.sock)."
return 0
else
echo "[ERROR] Docker socket /var/run/docker.sock not found."
echo "[SOLUTION] Please start Docker Desktop on Windows and enable WSL integration, then mount /var/run/docker.sock into the container."
return 1
fi
fi
# Check if running on macOS
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "[INFO] Running on Linux. Attempting to start Docker service..."
if command -v systemctl >/dev/null 2>&1; then
echo "[INFO] Starting Docker with systemctl..."
sudo systemctl start docker
sleep 2
if systemctl is-active --quiet docker; then
echo "[OK] Docker service started successfully via systemctl."
return 0
else
echo "[ERROR] Failed to start Docker using systemctl."
return 1
fi
elif command -v service >/dev/null 2>&1; then
echo "[INFO] systemctl not found, trying to start Docker using service..."
sudo service docker start
sleep 2
if docker info >/dev/null 2>&1; then
echo "[OK] Docker service started successfully via service command."
return 0
else
echo "[ERROR] Failed to start Docker using service command."
return 1
fi
else
echo "[ERROR] Neither systemctl nor service command found. Please start Docker manually."
return 1
fi
fi
return 1
}
check_docker_running() {
echo "==> Checking if Docker service is running..."
# if Docker CLI is installed and Docker daemon is running
if docker info >/dev/null 2>&1; then
echo "==> Docker is running."
return 0
fi
# if running on WSL, check for Docker socket
if grep -qi microsoft /proc/version; then
echo "[INFO] Detected WSL environment. Verifying /var/run/docker.sock..."
if [ -S /var/run/docker.sock ]; then
echo "==> Docker socket found. Docker should be available via Docker Desktop."
return 0
else
echo "[ERROR] Docker socket not found in WSL environment."
return 1
fi
fi
echo "==> Docker is not running. Attempting to start it..."
# Start Docker service using systemctl or service command
if command -v systemctl &>/dev/null; then
if systemctl list-units --type=service | grep -q "docker.service"; then
echo "==> Starting Docker with systemctl..."
sudo systemctl start docker && echo "==> Docker started successfully." && return 0
fi
fi
if command -v service &>/dev/null; then
if service --status-all | grep -q "docker"; then
echo "==> Starting Docker with service..."
sudo service docker start && echo "==> Docker started successfully." && return 0
fi
fi
if command -v snap &>/dev/null && snap list | grep -q "docker"; then
echo "==> Starting Docker with snap..."
sudo snap start docker && echo "==> Docker started successfully." && return 0
fi
echo "ERROR: Unable to start Docker automatically. Please start it manually."
return 1
}
start_local_gitea(){
echo "[INFO] Starting Gitea container..."
GITEA_CONTAINER_NAME="freeleaps2-gitea"
GITEA_IMAGE="gitea/gitea:latest"
# If a container with the same name exists, remove it
if docker ps -a --format '{{.Names}}' | grep -q "^${GITEA_CONTAINER_NAME}\$"; then
echo "==> Removing existing Gitea container..."
docker stop "${GITEA_CONTAINER_NAME}" &>/dev/null || true
docker rm "${GITEA_CONTAINER_NAME}" &>/dev/null || true
fi
# Pull the Gitea image
echo "==> Pulling Gitea image: ${GITEA_IMAGE}"
if ! docker pull "${GITEA_IMAGE}"; then
echo "ERROR: Failed to pull Gitea image: ${GITEA_IMAGE}"
exit 1
fi
# Run the Gitea container mapping port 3000
gitea_container_id=$(docker run -d --name "${GITEA_CONTAINER_NAME}" \
-v "${WORKING_HOME}/gitea:/data" \
-e "DISABLE_REGISTRATION=true" \
-e "REQUIRE_SIGNIN_VIEW=true" \
-p 3000:3000 "${GITEA_IMAGE}" )
if [[ -z "${gitea_container_id}" ]]; then
echo "ERROR: Failed to start Gitea container."
exit 1
fi
echo "Gitea container started successfully: ${gitea_container_id}"
# Allow Gitea some time to initialize
sleep 20
# Check Gitea health via curl
if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 &>/dev/null; then
echo "Gitea health check passed."
else
echo "ERROR: Gitea health check failed."
exit 1
fi
echo "$gitea_container_id" > "$WORKING_HOME/.gitea-instance"
echo "[INFO] Completed Gitea container..."
}
start_local_mongodb() {
echo "==> Starting MongoDB service..."
MONGO_CONTAINER_NAME="freeleaps2-mongodb"
MONGO_IMAGE="mongo:latest"
# if a container with the same name exists, remove it
if docker ps -a --format '{{.Names}}' | grep -q "^${MONGO_CONTAINER_NAME}\$"; then
echo "==> Removing existing MongoDB container..."
docker stop "$MONGO_CONTAINER_NAME" &>/dev/null || true
docker rm "$MONGO_CONTAINER_NAME" &>/dev/null || true
fi
echo "==> Pulling MongoDB image: $MONGO_IMAGE"
if ! docker pull "$MONGO_IMAGE"; then
echo "ERROR: Failed to pull MongoDB image: $MONGO_IMAGE"
exit 1
fi
echo "==> Starting MongoDB container..."
mongo_container_id=$(docker run -d --name "$MONGO_CONTAINER_NAME" -p 27017:27017 "$MONGO_IMAGE" mongod --bind_ip_all)
if [[ -z "$mongo_container_id" ]]; then
echo "ERROR: Failed to start MongoDB container."
exit 1
fi
echo "MongoDB container started successfully: $mongo_container_id"
sleep 10
MAX_ATTEMPTS=10
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
if docker exec "$MONGO_CONTAINER_NAME" mongosh --eval "db.adminCommand('ping')" 2>/dev/null | grep -q '{ ok: 1 }'; then
echo "MongoDB health check passed."
break
fi
echo "Waiting for MongoDB to be ready... (Attempt $((ATTEMPT+1)))"
sleep 10
ATTEMPT=$((ATTEMPT+1))
done
if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
echo "ERROR: MongoDB health check failed."
exit 1
fi
echo "$mongo_container_id" > "$WORKING_HOME/.mongodb-instance"
echo "==> Completed MongoDB container..."
}
start_local_rabbitMQ(){
echo "[INFO] Starting RabbitMQ container..."
RABBITMQ_CONTAINER_NAME="freeleaps2"
RABBITMQ_IMAGE="rabbitmq:latest"
# If a container with the same name exists, remove it
if docker ps -a --format '{{.Names}}' | grep -q "^${RABBITMQ_CONTAINER_NAME}\$"; then
echo "==> Removing existing RabbitMQ container..."
docker stop "${RABBITMQ_CONTAINER_NAME}" &>/dev/null || true
docker rm "${RABBITMQ_CONTAINER_NAME}" &>/dev/null || true
fi
# Pull the RabbitMQ image
echo "==> Pulling RabbitMQ image: ${RABBITMQ_IMAGE}"
if ! docker pull "${RABBITMQ_IMAGE}"; then
echo "ERROR: Failed to pull RabbitMQ image: ${RABBITMQ_IMAGE}"
exit 1
fi
# Run the RabbitMQ container mapping port 5672
rabbitmq_container_id=$(docker run -d --name "${RABBITMQ_CONTAINER_NAME}" -p 5672:5672 "${RABBITMQ_IMAGE}")
if [[ -z "${rabbitmq_container_id}" ]]; then
echo "ERROR: Failed to start RabbitMQ container."
exit 1
fi
echo "RabbitMQ container started successfully: ${rabbitmq_container_id}"
# Allow RabbitMQ some time to initialize
sleep 20
# Check RabbitMQ health via rabbitmqctl
if docker exec "${RABBITMQ_CONTAINER_NAME}" rabbitmqctl status &>/dev/null; then
echo "RabbitMQ health check passed."
else
echo "ERROR: RabbitMQ health check failed."
exit 1
fi
echo "$rabbitmq_container_id" > "$WORKING_HOME/.rabbitmq-instance"
echo "[INFO] Completed RabbitMQ container..."
}
# Define the local components and their corresponding ports
local_components_ports_keys=("devsvc" "notification" "content" "central_storage" "authentication")
local_components_ports_values=("8007" "8003" "8013" "8005" "8004")
# Get the port number for a local component
get_port() {
local comp="$1"
local port=""
for i in "${!local_components_ports_keys[@]}"; do
if [ "${local_components_ports_keys[i]}" = "$comp" ]; then
port="${local_components_ports_values[i]}"
break
fi
done
echo "$port"
}
# :command.command_functions
# :command.function
devbox_init_command() {
#!/usr/bin/env bash
echo "==> [INIT] Starting DevBox environment initialization..."
echo
# -------------------------------------------------------------------
# 1. Get parameters from command line arguments
# -------------------------------------------------------------------
local OS="$args_os" # --os
local ARCH="$args_arch" # --arch
local DEVBOX_NAME="$args_devbox_container_name" # --devbox-container-name
local DEVBOX_PORT="$args_devbox_container_port" # --devbox-container-port
local DEVBOX_FRONTEND_PORT="$args_devbox_frontend_port" # --devbox-frontend-port
local DEVBOX_BACKEND_PORT="$args_devbox_backend_port" # --devbox-backend-port
local DEVBOX_REPO="$args_devbox_image_repo" # --devbox-image-repo
local DEVBOX_IMAGE="$args_devbox_image_name" # --devbox-image-name
local DEVBOX_TAG="$args_devbox_image_tag" # --devbox-image-tag
local WORKING_HOME="${args_working_home:-${WORKING_HOME:-${HOME}/.devbox}}"
local FREELEAPS_USERNAME="$args_freeleaps_username" # --freeleaps-username
local FREELEAPS_PASSWORD="$args_freeleaps_password" # --freeleaps-password
local USE_LOCAL_COMPONENT="$args_use_local_component" # --use-local-component
local DEVSVC_REPO="$args_devsvc_image_repo" # --devsvc-image-repo
local DEVSVC_IMAGE="$args_devsvc_image_image" # --devsvc-image-image
local DEVSVC_TAG="$args_devsvc_image_tag" # --devsvc-image-tag
local CONTENT_REPO="$args_content_image_repo" # --content-image-repo
local CONTENT_IMAGE="$args_content_image_image" # --content-image-image
local CONTENT_TAG="$args_content_image_tag" # --content-image-tag
local CENTRAL_STORAGE_REPO="$args_central_storage_image_repo" # --central_storage-image-repo
local CENTRAL_STORAGE_IMAGE="$args_central_storage_image_image" # --central_storage-image-image
local CENTRAL_STORAGE_TAG="$args_central_storage_image_tag" # --central_storage-image-tag
local AUTHENTICATION_REPO="$args_authentication_image_repo" # --authentication-image-repo
local AUTHENTICATION_IMAGE="$args_authentication_image_image" # --authentication-image-image
local AUTHENTICATION_TAG="$args_authentication_image_tag" # --authentication-image-tag
local NOTIFICATION_REPO="$args_notification_image_repo" # --notification-image-repo
local NOTIFICATION_IMAGE="$args_notification_image_image" # --notification-image-image
local NOTIFICATION_TAG="$args_notification_image_tag" # --notification-image-tag
# --force flag to overwrite existing resources
local FORCE_INIT="${args_force}"
local OS="$(get_arg '--os')"
local ARCH="$(get_arg '--arch')"
local DEVBOX_NAME="$(get_arg '--devbox-container-name')"
local DEVBOX_PORT="$(get_arg '--devbox-container-port')"
local DEVBOX_FRONTEND_PORT="$(get_arg '--devbox-frontend-port')"
local DEVBOX_BACKEND_PORT="$(get_arg '--devbox-backend-port')"
local DEVBOX_REPO="$(get_arg '--devbox-image-repo')"
local DEVBOX_IMAGE="$(get_arg '--devbox-image-name')"
local DEVBOX_TAG="$(get_arg '--devbox-image-tag')"
local WORKING_HOME="$(get_arg '--working-home' "${WORKING_HOME:-${HOME}/.devbox}")"
local FREELEAPS_USERNAME="$(get_arg '--freeleaps-username')"
local FREELEAPS_PASSWORD="$(get_arg '--freeleaps-password')"
local USE_LOCAL_COMPONENT="$(get_arg '--use-local-component')"
local DEVSVC_REPO="$(get_arg '--devsvc-image-repo')"
local DEVSVC_IMAGE="$(get_arg '--devsvc-image-name')"
local DEVSVC_TAG="$(get_arg '--devsvc-image-tag')"
local CONTENT_REPO="$(get_arg '--content-image-repo')"
local CONTENT_IMAGE="$(get_arg '--content-image-name')"
local CONTENT_TAG="$(get_arg '--content-image-tag')"
local CENTRAL_STORAGE_REPO="$(get_arg '--central_storage-image-repo')"
local CENTRAL_STORAGE_IMAGE="$(get_arg '--central_storage-image-name')"
local CENTRAL_STORAGE_TAG="$(get_arg '--central_storage-image-tag')"
local AUTHENTICATION_REPO="$(get_arg '--authentication-image-repo')"
local AUTHENTICATION_IMAGE="$(get_arg '--authentication-image-name')"
local AUTHENTICATION_TAG="$(get_arg '--authentication-image-tag')"
local NOTIFICATION_REPO="$(get_arg '--notification-image-repo')"
local NOTIFICATION_IMAGE="$(get_arg '--notification-image-name')"
local NOTIFICATION_TAG="$(get_arg '--notification-image-tag')"
local FORCE_INIT="$(get_arg '--force')"
local is_pull_all_components=true
local components=("devsvc" "notification" "content" "central_storage" "authentication")
local start_components=()
echo "==> Checking parameters..."
for component in "${components[@]}"; do
echo "==> Checking ${component} image repo...value: $(get_arg "--${component}-image-repo")"
if [[ -n "$(get_arg "--${component}-image-repo")" ]]; then
is_pull_all_components=false
else
start_components+=("${component}")
fi
# Check ARCH match default component tag value and justify the default Image tag value
if [[ "$ARCH" == "amd64" && "$component" == "devsvc" ]]; then
DEVSVC_TAG="latest-linux-amd64"
elif [[ "$ARCH" == "arm64" && "$component" == "devsvc" ]]; then
DEVSVC_TAG="latest-linux-arm64"
fi
if [[ "$ARCH" == "amd64" && "$component" == "content" ]]; then
CONTENT_TAG="latest-linux-amd64"
elif [[ "$ARCH" == "arm64" && "$component" == "content" ]]; then
CONTENT_TAG="latest-linux-arm64"
fi
if [[ "$ARCH" == "amd64" && "$component" == "central_storage" ]]; then
CENTRAL_STORAGE_TAG="latest-linux-amd64"
elif [[ "$ARCH" == "arm64" && "$component" == "central_storage" ]]; then
CENTRAL_STORAGE_TAG="latest-linux-arm64"
fi
if [[ "$ARCH" == "amd64" && "$component" == "authentication" ]]; then
AUTHENTICATION_TAG="latest-linux-amd64"
elif [[ "$ARCH" == "arm64" && "$component" == "authentication" ]]; then
AUTHENTICATION_TAG="latest-linux-arm64"
fi
if [[ "$ARCH" == "amd64" && "$component" == "notification" ]]; then
NOTIFICATION_TAG="latest-linux-amd64"
elif [[ "$ARCH" == "arm64" && "$component" == "notification" ]]; then
NOTIFICATION_TAG="latest-linux-arm64"
fi
done
echo "==> is_pull_all_components: $is_pull_all_components"
echo " ===================================================== "
echo "Parameters:"
echo " OS = $OS"
echo " ARCH = $ARCH"
echo " DEVBOX_NAME = $DEVBOX_NAME"
echo " DEVBOX_PORT = $DEVBOX_PORT"
echo " DEVBOX_FRONTEND_PORT = $DEVBOX_FRONTEND_PORT"
echo " DEVBOX_BACKEND_PORT = $DEVBOX_BACKEND_PORT"
echo " DEVBOX_REPO = $DEVBOX_REPO"
echo " DEVBOX_IMAGE = $DEVBOX_IMAGE"
echo " DEVBOX_TAG = $DEVBOX_TAG"
echo " WORKING_HOME = $WORKING_HOME"
echo " FREELEAPS_USERNAME= $FREELEAPS_USERNAME"
echo " (FREELEAPS_PASSWORD is hidden for security)"
echo " USE_LOCAL_COMPONENT= $USE_LOCAL_COMPONENT"
echo " DEVSVC_REPO = $DEVSVC_REPO"
echo " DEVSVC_IMAGE = $DEVSVC_IMAGE"
echo " DEVSVC_TAG = $DEVSVC_TAG"
echo " CONTENT_REPO = $CONTENT_REPO"
echo " CONTENT_IMAGE = $CONTENT_IMAGE"
echo " CONTENT_TAG = $CONTENT_TAG"
echo " CENTRAL_STORAGE_REPO = $CENTRAL_STORAGE_REPO"
echo " CENTRAL_STORAGE_IMAGE= $CENTRAL_STORAGE_IMAGE"
echo " CENTRAL_STORAGE_TAG = $CENTRAL_STORAGE_TAG"
echo " AUTHENTICATION_REPO = $AUTHENTICATION_REPO"
echo " AUTHENTICATION_IMAGE= $AUTHENTICATION_IMAGE"
echo " AUTHENTICATION_TAG = $AUTHENTICATION_TAG"
echo " NOTIFICATION_REPO = $NOTIFICATION_REPO"
echo " NOTIFICATION_IMAGE= $NOTIFICATION_IMAGE"
echo " NOTIFICATION_TAG = $NOTIFICATION_TAG"
echo " FORCE_INIT = $FORCE_INIT"
echo
# -------------------------------------------------------------------
# 2. Check OS/ARCH support
# (if using auto, detect current system, here just show simple check)
# -------------------------------------------------------------------
if [[ "$OS" != "auto" && "$OS" != "linux" && "$OS" != "darwin" && "$OS" != "wsl2" ]]; then
echo "ERROR: Unsupported OS: $OS"
exit 1
fi
if [[ "$ARCH" != "auto" && "$ARCH" != "amd64" && "$ARCH" != "arm64" ]]; then
echo "ERROR: Unsupported architecture: $ARCH"
exit 1
fi
# Check ARCH match current device
if [[ "$ARCH" == "auto" ]]; then
ARCH="$(uname -m)"
if [[ "$ARCH" == "x86_64" ]]; then
ARCH="amd64"
elif [[ "$ARCH" == "aarch64" ]]; then
ARCH="arm64"
else
echo "ERROR: Unsupported architecture: $ARCH"
exit 1
fi
fi
echo "==> Detected OS: $OS, ARCH: $ARCH"
# Default arch tag value if Arch is amd64 then latest-linux-amd64 else latest-linux-arm64
local arch_tag="latest-linux-${ARCH}"
# -------------------------------------------------------------------
# 3. Check environment requirements
# -------------------------------------------------------------------
# 3.1 Docker Check
if ! command -v docker &>/dev/null; then
echo "ERROR: docker is not installed or not in PATH."
exit 1
fi
# 3.2 Check disk space
local free_space_kb
free_space_kb="$(df -Pk "$HOME" | awk 'END{print $4}')"
# 若无法获取或小于 10GB (10485760 KB),报错
if [[ -z "$free_space_kb" || $free_space_kb -lt 10485760 ]]; then
echo "ERROR: Insufficient disk space (need >10GB)."
exit 1
fi
# 3.3 WORKING_HOME Check
if ! mkdir -p "$WORKING_HOME" 2>/dev/null; then
echo "ERROR: Can't create or write to WORKING_HOME: $WORKING_HOME"
exit 1
fi
# 3.4 Network to docker.com(sampleping docker.com)
if ! ping -c 1 docker.com &>/dev/null; then
echo "ERROR: Network unreachable."
exit 1
fi
# -------------------------------------------------------------------
# 4. If .devbox-instance exists, --forceuse it
# -------------------------------------------------------------------
if [[ -f "$WORKING_HOME/.devbox-instance" && -z "$FORCE_INIT" ]]; then
echo "ERROR: DevBox already initialized. Use --force to overwrite."
exit 1
fi
# -------------------------------------------------------------------
# 5.install docker and check docker running
# -------------------------------------------------------------------
if ! install_docker; then
echo "ERROR: Failed to install Docker or Docker service is not running."
exit 1
fi
if ! check_docker_running; then
echo "ERROR: Docker service is not running."
exit 1
fi
# -------------------------------------------------------------------
# 5.1 pull and start DevBox container
# -------------------------------------------------------------------
local devbox_full_image="${DEVBOX_REPO}/${DEVBOX_IMAGE}:${DEVBOX_TAG}"
echo "==> Pulling DevBox image: $devbox_full_image"
if ! docker pull "$devbox_full_image"; then
echo "ERROR: Failed to pull DevBox image: $devbox_full_image"
exit 1
fi
# If container with same name exists, remove it
if docker ps -a --format '{{.Names}}' | grep -q "^${DEVBOX_NAME}\$"; then
if [[ -n "$FORCE_INIT" ]]; then
echo "==> Removing existing container named $DEVBOX_NAME ..."
docker stop "$DEVBOX_NAME" &>/dev/null || true
docker rm "$DEVBOX_NAME" &>/dev/null || true
else
echo "ERROR: Container named $DEVBOX_NAME already exists. Use --force to remove it."
exit 1
fi
fi
DEVBOX_FREELEAPS2_NETWORK="devbox_freeleaps2-network"
echo '==> [INIT] Starting DevBox environment initialization...'
# Check if docker network create devbox_freeleaps2-network
if ! docker network ls | grep -q "$DEVBOX_FREELEAPS2_NETWORK"; then
echo "==> Creating Docker network: $DEVBOX_FREELEAPS2_NETWORK"
docker network create "$DEVBOX_FREELEAPS2_NETWORK"
else
echo "==> Docker network devbox_freeleaps2-network already exists."
fi
echo '==> [INIT] Starting DevBox container...'
# Create and start DevBox container
local container_id
container_id="$(
docker run -d \
--name "$DEVBOX_NAME" \
-p "${DEVBOX_PORT}:22" \
-p "${DEVBOX_FRONTEND_PORT}:5173" \
-p "${DEVBOX_BACKEND_PORT}:8002" \
-v "$WORKING_HOME:/home/.devbox" \
-v /var/run/docker.sock:/var/run/docker.sock \
--network "$DEVBOX_FREELEAPS2_NETWORK" \
"$devbox_full_image" 2>/dev/null
)"
if [[ -z "$container_id" ]]; then
echo "ERROR: Failed to create DevBox container."
exit 1
fi
# record container id, DEVBOX_FRONTEND_PORT, DEVBOX_BACKEND_PORT
echo "$container_id" > "$WORKING_HOME/.devbox-instance"
echo "$DEVBOX_FRONTEND_PORT" > "$WORKING_HOME/.devbox-frontend-port"
echo "$DEVBOX_BACKEND_PORT" > "$WORKING_HOME/.devbox-backend-port"
# -------------------------------------------------------------------
# 6. linbwang: pull and start other components
# -------------------------------------------------------------------
echo "==> [INIT] Starting Freeleaps services... Use Local component $USE_LOCAL_COMPONENT"
if [[ "$(lower "$USE_LOCAL_COMPONENT")" == "true" ]]; then
echo ' ===> Using local components for Freeleaps services.'
export ARCH="$ARCH"
export DEVSVC_IMAGE_TAG="$DEVSVC_TAG"
export CONTENT_IMAGE_TAG="$CONTENT_TAG"
export CENTRAL_STORAGE_IMAGE_TAG="$CENTRAL_STORAGE_TAG"
export AUTHENTICATION_IMAGE_TAG="$AUTHENTICATION_TAG"
export NOTIFICATION_IMAGE_TAG="$NOTIFICATION_TAG"
# Start local components by docker compose file and start up specified services. docker compose file is in the same directory as the script (docker-compose.dev.arm64.new.yaml)
# start component service from start_components array
docker-compose -f docker-compose.dev.arm64.new.yaml up -d mongodb rabbitmq gitea "${start_components[@]}"
echo "==> Starting Gitea, MongoDB, RabbitMQ containers..."
gitea_container_id=$(docker ps --no-trunc -a --filter "name=^freeleaps2-gitea$" --format "{{.ID}}")
echo "$gitea_container_id" > "$WORKING_HOME/.gitea-instance"
mongo_container_id=$(docker ps --no-trunc -a --filter "name=^freeleaps2-mongodb$" --format "{{.ID}}")
echo "$mongo_container_id" > "$WORKING_HOME/.mongodb-instance"
rabbitmq_container_id=$(docker ps --no-trunc -a --filter "name=^freeleaps2-rabbitmq$" --format "{{.ID}}")
echo "$rabbitmq_container_id" > "$WORKING_HOME/.rabbitmq-instance"
# Get all components container ids and save to .component-instance file
for component in "${start_components[@]}"; do
tmp_container_id=$(docker ps --no-trunc -a --filter "name=^$component$" --format "{{.ID}}")
echo "$tmp_container_id" > "$WORKING_HOME/.${component}-instance"
done
echo "${component} container created: $component_container_id"
else
echo '============================================'
echo ' ===> Using online components for Freeleaps services.'
echo '============================================'
# Start Gitea, MongoDB, RabbitMQ containers
local_components_docker_compose_output=$(docker-compose -f docker-compose.dev.arm64.new.yaml up -d mongodb rabbitmq)
if [[ -z "$local_components_docker_compose_output" ]]; then
echo "ERROR: Failed to start MongoDB, RabbitMQ containers."
exit 1
fi
# Save MongoDB and RabbitMQ container ids to .mongodb-instance and .rabbitmq-instance
mongo_container_id=$(docker ps -a --format '{{.Names}}' | grep "^freeleaps2-mongodb\$")
echo "$mongo_container_id" > "$WORKING_HOME/.mongodb-instance"
rabbitmq_container_id=$(docker ps -a --format '{{.Names}}' | grep "^freeleaps2-rabbitmq\$")
echo "$rabbitmq_container_id" > "$WORKING_HOME/.rabbitmq-instance"
fi
pushd $WORKING_HOME
# Make a user input (Y/N) to continue pull freeleaps.com code and start if N then exit
read -p "Do you want to continue to pull freeleaps.com code and start the services? (Y/N): " user_input
if [[ "$user_input" == "N" || "$user_input" == "n" ]]; then
# Echo as init job completed and exit
echo "==> [INIT] DevBox environment initialization completed."
exit 0
fi
# Check if freeleaps2-frontend exists, if not git clone it
if [ ! -d $WORKING_HOME/freeleaps ]; then
echo "Git cloning freeleaps.com:3443/products/freeleaps.git"
FRONTEND_GIT_URL="https://$FREELEAPS_USERNAME:$FREELEAPS_PASSWORD@freeleaps.com:3443/products/freeleaps.git"
git clone --depth 5 $FRONTEND_GIT_URL
else
pushd $WORKING_HOME/freeleaps
echo "Git pulling freeleaps.com:3443/products/freeleaps.git"
git pull
fi
# Run banckend service and frontend service in the container
docker exec -i "$DEVBOX_NAME" bash <<EOF
# Set environment variables
export FREELEAPS_USERNAME="${FREELEAPS_USERNAME}"
export FREELEAPS_PASSWORD="${FREELEAPS_PASSWORD}"
export USE_LOCAL_COMPONENT="${USE_LOCAL_COMPONENT}"
export DEVBOX_BACKEND_PORT="${DEVBOX_BACKEND_PORT}"
export DEVBOX_FRONTEND_PORT="${DEVBOX_FRONTEND_PORT}"
# Check if useing local component and update /home/.devbox/freeleaps/.dev.env
echo "step 2: Update /home/.devbox/freeleaps/apps/.env"
# Get default IP address
DEFAULT_IP=\$(ip route | grep default | sed -n 's/.*default via \([^ ]*\).*/\1/p')
if [[ "\$(lower "\$USE_LOCAL_COMPONENT")" == "true" ]]; then
echo "==> Using local components"
# Local components for Freeleaps services (devsvc, notification, content, central_storage, authentication)
cat << 'EOFinner' > /home/.devbox/freeleaps/apps/.env
# Online endpoint info
export MONGODB_NAME=freeleaps2
export MONGODB_URI=mongodb://\$DEFAULT_IP:27017/
export MONGODB_PORT=27017
export BLOB_STORE_CONNECTION_STR="DefaultEndpointsProtocol=https;AccountName=freeleaps1static;AccountKey=SIk7S3RviJxl1XhGiDZKA3cvzfxNrSbsBMfJ3EbKTsKPeMwhy8FTLpJliRLzQVE6uaSX8giDYw2h+ASt5MmHxQ==;EndpointSuffix=core.windows.net"
export RABBITMQ_HOSTNAME=freeleaps2
export RABBITMQ_HOST=\$DEFAULT_IP
export RABBITMQ_PORT=5672
export FREELEAPS_ENV=dev
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd
export STRIPE_WEBHOOK_SECRET=whsec_S6ZWjSAdR5Cpsn2USH6ZRBqbdBIENjTC
export STRIPE_ACCOUNT_WEBHOOK_SECRET=whsec_PgPnkWGhEUiQfnV8aIb5Wmruz7XETJLm
export SITE_URL_ROOT=http://\$DEFAULT_IP/
export FREELEAPS_DEVSVC_ENDPOINT=http://\$DEFAULT_IP:8007/api/devsvc/
export FREELEAPS_CONTENT_ENDPOINT=http://\$DEFAULT_IP:8013/api/content/
export FREELEAPS_NOTIFICATION_ENDPOINT=http://\$DEFAULT_IP:8003/api/notification/
export FREELEAPS_CENTRAL_STORAGE_ENDPOINT=http://\$DEFAULT_IP:8005/api/central_storage/
export FREELEAPS_AUTHENTICATION_ENDPOINT=http://\$DEFAULT_IP:8004/api/auth/
export FREELEAPS_AILAB_ENDPOINT=https://as010-w2-re-vm.mathmast.com:8009/api/
export KAFKA_SERVER_URL=''
export EMAIL_FROM=freeleaps@freeleaps.com
EOFinner
else
cat << 'EOFinner' > /home/.devbox/freeleaps/apps/.env
# Online endpoint info
export MONGODB_NAME=freeleaps2
export MONGODB_PORT=27017
export MONGODB_URI='mongodb+srv://jetli:8IHKx6dZK8BfugGp@freeleaps2.hanbj.mongodb.net/'
export RABBITMQ_HOSTNAME=freeleaps2
export RABBITMQ_HOST=52.149.35.244
export RABBITMQ_PORT=5672
export FREELEAPS_ENV=dev
export STRIPE_API_KEY=sk_test_51Ogsw5B0IyqaSJBrwczlr820jnmvA1qQQGoLZ2XxOsIzikpmXo4pRLjw4XVMTEBR8DdVTYySiAv1XX53Zv5xqynF00GfMqttFd
export STRIPE_WEBHOOK_SECRET=whsec_S6ZWjSAdR5Cpsn2USH6ZRBqbdBIENjTC
export STRIPE_ACCOUNT_WEBHOOK_SECRET=whsec_PgPnkWGhEUiQfnV8aIb5Wmruz7XETJLm
export SITE_URL_ROOT=http://localhost/
export FREELEAPS_DEVSVC_ENDPOINT=http://52.149.3.85:8007/api/devsvc/
export FREELEAPS_CONTENT_ENDPOINT=http://52.149.35.244:8013/api/content/
export FREELEAPS_NOTIFICATION_ENDPOINT=http://52.149.35.244:8003/api/notification/
export FREELEAPS_CENTRAL_STORAGE_ENDPOINT=http://52.149.35.244:8005/api/central_storage/
export FREELEAPS_AUTHENTICATION_ENDPOINT=http://52.149.35.244:8004/api/auth/
export FREELEAPS_AILAB_ENDPOINT=https://as010-w2-re-vm.mathmast.com:8009/api/
export KAFKA_SERVER_URL=''
export EMAIL_FROM=freeleaps@freeleaps.com
EOFinner
fi
# Effect the environment variables in the current shell
source /home/.devbox/freeleaps/apps/.env
# Ensure /home/.devbox/logs exists
mkdir -p /home/.devbox/logs
# Start WebAPI service
echo "Starting WebAPI service..."
pushd /home/.devbox/freeleaps/apps
cp /home/.devbox/freeleaps/backend_env.sh /home/.devbox/freeleaps/apps/backend_env.sh
# 5. Istall python3.10 and venv module
echo "5. Istall python3.10 and venv module"
sudo apt update
sudo apt install python3.10 python3.10-venv -y
# make sore python3.10 is installed
if ! command -v python3.10 &>/dev/null; then
echo "ERROR: Python3.10 is not installed."
exit 1
fi
# Upgrade pip and install virtualenv
echo "7. Upgrade pip and install virtualenv"
python3.10 -m ensurepip --upgrade
python3.10 -m pip install --upgrade pip
# 8. Create and activate a virtual environment
echo "8. Create and activate a virtual environment"
python3.10 -m venv venv_t
sleep 5
# CHeck if the virtual environment is created
if [ ! -f "venv_t/bin/activate" ]; then
echo "ERROR: The virtual environment cannot be created"
exit 1
fi
echo '============================================'
echo ' Start to activate virtual environment'
echo '============================================'
source venv_t/bin/activate
source /home/.devbox/freeleaps/apps/.env
# Verify the virtual environment is activated
if [[ "\$VIRTUAL_ENV" != "" ]]; then
echo "Virtual environment activate: \$VIRTUAL_ENV"
else
echo "ERROR: The virtual environment cannot be startup \$VIRTUAL_ENV"
exit 1
fi
echo '============================================'
echo ' Install requirements'
echo '============================================'
pip install -r /home/.devbox/freeleaps/apps/requirements.txt
echo '============================================'
echo 'Start to run start_webapi.sh'
echo '============================================'
./start_webapi.sh > /home/.devbox/logs/backend.logs 2>&1 &
BACKEND_PID=\$!
# Save BACKEND_PID to a file \${WORKING_HOME}/.backend.pid: Stores the process id of backend process.
echo "\$BACKEND_PID" > /home/.devbox/.backend.pid
echo '============================================'
echo 'Check if the WebAPI service started successfully'
echo '============================================'
sleep 30
# 30 attempts, 5 seconds each, total wait time 2.5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
echo "Waiting for WebAPI service to become healthy..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_BACKEND_PORT/docs")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Backend Swagger UI is available at \$URL (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Swagger UI to become available... Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 5 # Wait 5 seconds
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: WebAPI failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
echo '============================================'
echo ' Start frontend service locally'
echo '============================================'
pushd /home/.devbox/freeleaps/frontend
# start the frontend service
export VITE_API_URL='http://127.0.0.1:8002'
export VITE_WEBSOCKET_URL='http://127.0.0.1:8002'
npm install
npm update
npm install -g pnpm
pnpm install
npm run build
npm run format
# Start the frontend service with nohup in order to keep it running after the SSH session is closed. Save the process ID of the frontend service
nohup npm run dev > /home/.devbox/logs/frontend.logs 2>&1 &
FRONTEND_PID=\$!
echo "npm run dev has been started with PID: \$FRONTEND_PID"
echo "\$FRONTEND_PID" > /home/.devbox/.frontend.pid
echo '============================================'
# Wait for the frontend service to start
sleep 30
# 30 attempts, 10 seconds each, total wait time 5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
echo "Waiting for Frontend service to start..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_FRONTEND_PORT/")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Frontend is available (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Frontend to become available... (http://localhost:\$DEVBOX_FRONTEND_PORT), (HTTP \$HTTP_CODE) Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 10
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: Frontend failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
echo "Freeleaps services started successfully"
EOF
# -------------------------------------------------------------------
# 10. Final notification
# -------------------------------------------------------------------
echo
echo "==========================================================="
echo "DevBox init completed successfully!"
echo " DevBox container ID: $WORKING_HOME/.devbox-instance"
echo " Repository cloned to: $WORKING_HOME/freeleaps"
echo " Backend logs: $WORKING_HOME/logs/backend.logs"
echo " Frontend logs: $WORKING_HOME/logs/frontend.logs"
echo " Backend PID: $WORKING_HOME/.backend.pid"
echo " Frontend PID: $WORKING_HOME/.frontend.pid"
echo "==========================================================="
echo
}
# :command.function
devbox_deinit_command() {
# src/deinit_command.sh
echo "# It contains the implementation for the 'devbox deinit' command."
local WORKING_HOME="$(get_arg '--working-home' "${HOME}/.devbox")"
local CLEAR_LOGS="$(get_arg '--clear-logs')"
local CLEAR_REPO="$(get_arg '--clear-repo')"
local FORCE="$(get_arg '--force')"
# print the parameters
echo "==> Deinitialization parameters:"
echo " WORKING_HOME = $WORKING_HOME"
echo " CLEAR_LOGS = $CLEAR_LOGS"
echo " CLEAR_REPO = $CLEAR_REPO"
echo " FORCE = $FORCE"
echo "==> Starting DevBox deinitialization..."
# Clear the DevBox container logs
if [[ "$CLEAR_LOGS" == "true" ]]; then
echo "==> Clearing logs in $WORKING_HOME/logs..."
rm -rf "$WORKING_HOME/logs"/* 2>/dev/null || true
else
echo "==> Skipping log clearing."
fi
# Clear the source repository
if [[ "$CLEAR_REPO" == "true" && -d "$WORKING_HOME/freeleaps" ]]; then
echo "==> Deleting source repository at $WORKING_HOME/freeleaps"
rm -rf "$WORKING_HOME/freeleaps"
else
echo "==> Skipping repository deletion."
fi
# Stop and remove DevBox container
if [[ -f "$WORKING_HOME/.devbox-instance" ]]; then
local container_id
container_id=$(cat "$WORKING_HOME/.devbox-instance")
echo "==> Stopping and removing DevBox container: $container_id"
docker stop "$container_id" &>/dev/null || true
docker rm "$container_id" &>/dev/null || true
rm -f "$WORKING_HOME/.devbox-instance"
# Remove the frontend and backend ports if the file exists
rm -f "$WORKING_HOME/.devbox-frontend-port"
rm -f "$WORKING_HOME/.devbox-backend-port"
# Remove the backend and frontend process IDs
rm -f "$WORKING_HOME/.backend.pid"
rm -f "$WORKING_HOME/.frontend.pid"
fi
if [[ -f "$WORKING_HOME/.gitea-instance" ]]; then
local gitea_container_id
gitea_container_id=$(cat "$WORKING_HOME/.gitea-instance")
echo "==> Stopping and removing Gitea container: $gitea_container_id"
docker stop "$gitea_container_id" &>/dev/null || true
docker rm "$gitea_container_id" &>/dev/null || true
rm -f "$WORKING_HOME/.gitea-instance"
fi
# Stop and remove MongoDB container
if [[ -f "$WORKING_HOME/.mongodb-instance" ]]; then
local mongodb_container_id
mongodb_container_id=$(cat "$WORKING_HOME/.mongodb-instance")
echo "==> Stopping and removing MongoDB container: $mongodb_container_id"
docker stop "$mongodb_container_id" &>/dev/null || true
docker rm "$mongodb_container_id" &>/dev/null || true
rm -f "$WORKING_HOME/.mongodb-instance"
fi
# Stop and remove RabbitMQ container
if [[ -f "$WORKING_HOME/.rabbitmq-instance" ]]; then
local rabbitmq_container_id
rabbitmq_container_id=$(cat "$WORKING_HOME/.rabbitmq-instance")
echo "==> Stopping and removing RabbitMQ container: $rabbitmq_container_id"
docker stop "$rabbitmq_container_id" &>/dev/null || true
docker rm "$rabbitmq_container_id" &>/dev/null || true
rm -f "$WORKING_HOME/.rabbitmq-instance"
fi
# Stop and remove other components
local components=("devsvc" "notification" "content" "central_storage" "authentication")
for component in "${components[@]}"; do
if [[ -f "$WORKING_HOME/.${component}-instance" ]]; then
local component_container_id
component_container_id=$(cat "$WORKING_HOME/.${component}-instance")
echo "==> Stopping and removing ${component} container: $component_container_id"
docker stop "$component_container_id" &>/dev/null || true
docker rm "$component_container_id" &>/dev/null || true
rm -f "$WORKING_HOME/.${component}-instance"
fi
done
echo "==> DevBox deinitialization completed."
}
# :command.function
devbox_start_command() {
local COMPONENT="$(get_arg '--component')"
local WORKING_HOME="$(get_arg '--working-home' "${HOME}/.devbox")"
# Check if the DevBox container is running
local devbox_container_id_file_path="${WORKING_HOME}/.devbox-instance"
if [[ ! -f "$devbox_container_id_file_path" ]]; then
echo "ERROR: DevBox container is not running. Please run 'devbox init' first."
exit 1
fi
local devbox_container_id=$(cat "$devbox_container_id_file_path")
echo "==> Starting DevBox services..."
# Check if DevBox container is running
if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${devbox_container_id}\$"; then
echo "==> DevBox container is not running, starting container..."
# Start the container
if ! docker start "${devbox_container_id}"; then
echo "ERROR: Failed to start DevBox container."
exit 1
fi
echo "==> DevBox container started successfully."
else
echo "==> DevBox container is already running."
fi
# If no component is specified, start all components
if [[ -z "$COMPONENT" ]]; then
COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend" "devsvc" "content" "central_storage" "authentication")
else
COMPONENTS=("$COMPONENT")
fi
# Start the specified components
for comp in "${COMPONENTS[@]}"; do
case "$comp" in
"mongodb")
echo "==> Starting MongoDB..."
# Check if MongoDB container file path
local mongodb_container_id_file_path="${WORKING_HOME}/.mongodb-instance"
if [[ ! -f "$mongodb_container_id_file_path" ]]; then
echo "ERROR: MongoDB container is not running. Please run 'devbox init' first."
else
local mongodb_container_id=$(cat "$mongodb_container_id_file_path")
if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${mongodb_container_id}\$"; then
echo "==> MongoDB container is not running, starting container..."
# Start the container
if ! docker start "${mongodb_container_id}"; then
echo "ERROR: Failed to start MongoDB container."
exit 1
fi
echo "==> MongoDB container started successfully."
else
echo "==> MongoDB container is already running."
fi
fi
;;
"rabbitmq")
echo "==> Starting RabbitMQ..."
# Check if RabbitMQ container file path
local rabbitmq_container_id_file_path="${WORKING_HOME}/.rabbitmq-instance"
if [[ ! -f "$rabbitmq_container_id_file_path" ]]; then
echo "ERROR: RabbitMQ container is not running. Please run 'devbox init' first."
else
local rabbitmq_container_id=$(cat "$rabbitmq_container_id_file_path")
if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${rabbitmq_container_id}\$"; then
echo "==> RabbitMQ container is not running, starting container..."
# Start the container
if ! docker start "${rabbitmq_container_id}"; then
echo "ERROR: Failed to start RabbitMQ container."
exit 1
fi
echo "==> RabbitMQ container started successfully."
else
echo "==> RabbitMQ container is already running."
fi
fi
;;
"backend")
echo "==> Starting backend service..."
# start the backend service
docker exec -i "$devbox_container_id" bash <<EOF
# Start the backend service
echo "Starting backend service..."
# Check if /home/.devbox/.backend.pid exists, if not exists, ask for executing devbox init first
if [ ! -f /home/.devbox/.backend.pid ]; then
echo "ERROR: Backend service is not running. Please run 'devbox init' first."
exit 1
fi
echo "Checking if the backend service is already running..."
backend_pid=\$(cat /home/.devbox/.backend.pid)
echo "Backend PID: \$backend_pid"
if ps -p "\$backend_pid" > /dev/null; then
echo "Backend service is already running."
else
# Remove the .backend.pid file
rm -f /home/.devbox/.backend.pid
echo '============================================'
echo 'Start to run start_webapi.sh'
echo '============================================'
pushd /home/.devbox/freeleaps/apps
./start_webapi.sh > /home/.devbox/logs/backend.logs 2>&1 &
BACKEND_PID=\$!
# Save BACKEND_PID to a file \${WORKING_HOME}/.frontend.pid: Stores the process id of frontend process.
echo "\$BACKEND_PID" > /home/.devbox/.backend.pid
echo '============================================'
echo 'Check if the WebAPI service started successfully'
echo '============================================'
sleep 30
# 30 attempts, 5 seconds each, total wait time 2.5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
# Check if \$DEVBOX_BACKEND_PORT exists
DEVBOX_BACKEND_PORT=\$(cat /home/.devbox/.devbox-backend-port)
if [ -z "\$DEVBOX_BACKEND_PORT" ]; then
echo "ERROR: DEVBOX_BACKEND_PORT is not set."
export DEVBOX_BACKEND_PORT=8002
fi
echo "Waiting for WebAPI service to become healthy..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_BACKEND_PORT/docs")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Backend Swagger UI is available at \$URL (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Swagger UI to become available... Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 5 # Wait 5 seconds
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: WebAPI failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
fi
EOF
;;
"frontend")
echo "==> Starting frontend service..."
# Start the frontend service
docker exec -i "$devbox_container_id" bash <<EOF
# Start the frontend service
echo "Starting frontend service..."
# Check if /home/.devbox/.frontend.pid exists
if [ -f /home/.devbox/.frontend.pid ]; then
frontend_pid=\$(cat /home/.devbox/.frontend.pid)
# Remove empty spaces and new lines in the frontend_pid
frontend_pid=\$(echo "\$frontend_pid" | tr -d '[:space:]')
# Check if frontend pid is empty
if [ -z "\$frontend_pid" ]; then
echo "Frontend service is not running. "
else
echo '============================================'
if ps -p "\$frontend_pid" > /dev/null; then
echo "Frontend service is already running."
exit 0
fi
fi
# Remove the .frontend.pid file before starting the frontend service
rm -f /home/.devbox/.frontend.pid
fi
echo '============================================'
echo ' Start frontend service locally'
echo '============================================'
pushd /home/.devbox/freeleaps/frontend
# Check if npm is installed and pnpm is installed and is npm run dev result is generated
if ! command -v npm &>/dev/null; then
echo "ERROR: npm is not installed."
exit 1
fi
if ! command -v pnpm &>/dev/null; then
echo "ERROR: pnpm is not installed."
exit 1
fi
if [ ! -f "package.json" ]; then
echo "ERROR: package.json not found."
exit 1
fi
# Start the frontend service with nohup in order to keep it running after the SSH session is closed
# Save the process ID of the frontend service
nohup npm run dev > /home/.devbox/logs/frontend.logs 2>&1 &
FRONTEND_PID=\$!
echo "npm run dev has been started with PID: \$FRONTEND_PID"
echo "\$FRONTEND_PID" > /home/.devbox/.frontend.pid
# Wait for the frontend service to start
sleep 10
# 30 attempts, 10 seconds each, total wait time 5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
DEVBOX_FRONTEND_PORT=\$(cat /home/.devbox/.devbox-frontend-port)
# get DEVBOX_FRONTEND_PORT from environment variables
if [ -z "\$DEVBOX_FRONTEND_PORT" ]; then
echo "ERROR: DEVBOX_FRONTEND_PORT is not set."
export DEVBOX_FRONTEND_PORT=5173
fi
echo "Waiting for Frontend service to start..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_FRONTEND_PORT/")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Frontend is available (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Frontend to become available... (http://localhost:\$DEVBOX_FRONTEND_PORT), (HTTP \$HTTP_CODE) Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 10
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: Frontend failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
EOF
;;
"devsvc" | "content" | "central_storage" | "authentication")
echo "==> Starting $comp service..."
# Check if the component container file exists
local component_container_id_file_path="${WORKING_HOME}/.${comp}-instance"
if [[ ! -f "$component_container_id_file_path" ]]; then
echo "ERROR: $comp container is not running. Please run 'devbox init' first."
else
local component_container_id=$(cat "$component_container_id_file_path")
if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${component_container_id}\$"; then
echo "==> $comp container is not running, starting container..."
# Start the container
if ! docker start "${component_container_id}"; then
echo "ERROR: Failed to start $comp container."
else
echo "==> $comp container started successfully."
fi
else
echo "==> $comp container is already running."
fi
fi
;;
*)
echo "ERROR: Unknown component: $comp"
exit 1
;;
esac
done
# If the frontend component is started, print the URL
if [[ " ${COMPONENTS[@]} " =~ " frontend " ]]; then
echo "==> Frontend started. You can access the Freeleaps web application at: http://localhost:5173"
fi
echo "==> DevBox services started successfully."
}
# :command.function
devbox_stop_command() {
echo "==> Stopping DevBox services..."
local COMPONENT="$(get_arg '--component')"
local WORKING_HOME="$(get_arg '--working-home' "${HOME}/.devbox")"
# If the DevBox container is not running, exit
if [[ -z "$COMPONENT" ]]; then
COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend" "devsvc" "content" "central_storage" "authentication")
else
COMPONENTS=("$COMPONENT")
fi
# Stop the specified components
for comp in "${COMPONENTS[@]}"; do
case "$comp" in
"mongodb")
echo "==> Stopping MongoDB..."
if [[ -f "${WORKING_HOME}/.mongodb-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.mongodb-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> MongoDB container is not running."
fi
;;
"rabbitmq")
echo "==> Stopping RabbitMQ..."
if [[ -f "${WORKING_HOME}/.rabbitmq-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.rabbitmq-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> RabbitMQ container is not running."
fi
;;
"backend")
echo "==> Stopping backend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> Backend service is not running."
fi
;;
"frontend")
echo "==> Stopping frontend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> Frontend service is not running."
fi
;;
"devsvc" | "content" | "central_storage" | "authentication")
echo "==> Stopping $comp service..."
if [[ -f "${WORKING_HOME}/.${comp}-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.${comp}-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> $comp service is not running."
fi
;;
*)
echo "ERROR: Unknown component: $comp"
exit 1
;;
esac
echo "==> $comp service stopped successfully."
done
echo "==> DevBox services stopped successfully."
}
# :command.function
devbox_status_command() {
echo "==> Checking DevBox services status..."
local COMPONENT="$(get_arg '--component')"
local WORKING_HOME="$(get_arg '--working-home' "${HOME}/.devbox")"
# Check if .devbox-instance file exists
if [[ ! -f "${WORKING_HOME}/.devbox-instance" ]]; then
echo "==> DevBox container is not running."
exit 1
fi
local devbox_container_id=$(cat "${WORKING_HOME}/.devbox-instance")
# If the DevBox container devbox_container_id is not running, exit
if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${devbox_container_id}\$"; then
echo "==> DevBox container is not running."
exit 1
fi
# If no component is specified, check all components
if [[ -z "$COMPONENT" ]]; then
COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend" "devsvc" "content" "central_storage" "authentication")
else
COMPONENTS=("$COMPONENT")
fi
# Check the status of the specified components
for comp in "${COMPONENTS[@]}"; do
case "$comp" in
"mongodb")
echo "==> Checking MongoDB status..."
if [[ -f "${WORKING_HOME}/.mongodb-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.mongodb-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: MongoDB container is running."
else
echo "[RESULT]: MongoDB container is not running."
fi
else
echo "[RESULT]: MongoDB container is not running."
fi
;;
"rabbitmq")
echo "==> Checking RabbitMQ status..."
if [[ -f "${WORKING_HOME}/.rabbitmq-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.rabbitmq-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: RabbitMQ container is running."
else
echo "[RESULT]: RabbitMQ container is not running."
fi
else
echo "[RESULT]: RabbitMQ container is not running."
fi
;;
"backend")
echo "==> Checking backend service status..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
if [[ -f "${WORKING_HOME}/.backend.pid" ]]; then
local backend_pid
backend_pid=$(cat "${WORKING_HOME}/.backend.pid")
if docker exec -i "$container_id" ps -p "$backend_pid" &>/dev/null; then
echo "[RESULT]: Backend service is running."
else
echo "[RESULT]: Backend service is not running."
fi
else
echo "[RESULT]: Backend service is not running."
fi
else
echo "[RESULT]: Backend service is not running."
fi
fi
;;
"frontend")
echo "==> Checking frontend service status..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
if [[ -f "${WORKING_HOME}/.frontend.pid" ]]; then
local frontend_pid
frontend_pid=$(cat "${WORKING_HOME}/.frontend.pid")
if docker exec -i "$container_id" ps -p "$frontend_pid" &>/dev/null; then
echo "[RESULT]: Frontend service is running."
else
echo "[RESULT]: Frontend service is not running."
fi
else
echo "[RESULT]: Frontend service is not running."
fi
else
echo "[RESULT]: Frontend service is not running."
fi
fi
;;
"devsvc")
echo "==> Checking devsvc service status..."
if [[ -f "${WORKING_HOME}/.devsvc-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devsvc-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: devsvc container is running."
else
echo "[RESULT]: devsvc container is not running."
fi
else
echo "[RESULT]: devsvc container is not running."
fi
;;
"content")
echo "==> Checking content service status..."
if [[ -f "${WORKING_HOME}/.content-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.content-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: content container is running."
else
echo "[RESULT]: content container is not running."
fi
else
echo "[RESULT]: content container is not running."
fi
;;
"central_storage")
echo "==> Checking central_storage service status..."
if [[ -f "${WORKING_HOME}/.central_storage-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.central_storage-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: central_storage container is running."
else
echo "[RESULT]: central_storage container is not running."
fi
else
echo "[RESULT]: central_storage container is not running."
fi
;;
"authentication")
echo "==> Checking authentication service status..."
if [[ -f "${WORKING_HOME}/.authentication-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.authentication-instance")
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${container_id}\$"; then
echo "[RESULT]: authentication container is running."
else
echo "[RESULT]: authentication container is not running."
fi
else
echo "[RESULT]: authentication container is not running."
fi
;;
*)
echo "ERROR: Unknown component: $comp"
exit 1
;;
esac
done
echo "==> DevBox services status checked successfully."
}
# :command.function
devbox_restart_command() {
echo "==> Restarting DevBox services..."
local COMPONENT="$(get_arg '--component')"
local WORKING_HOME="$(get_arg '--working-home' "${HOME}/.devbox")"
# Check devbox container file path
local devbox_container_id_file_path="${WORKING_HOME}/.devbox-instance"
if [[ ! -f "$devbox_container_id_file_path" ]]; then
echo "ERROR: DevBox container is not running. Please run 'devbox init' first."
exit 1
fi
local devbox_container_id=$(cat "$devbox_container_id_file_path")
if ! docker ps -a --no-trunc --format '{{.ID}}' | grep -q "^${devbox_container_id}\$"; then
echo "ERROR: DevBox container is not running. Please run 'devbox init' first."
rm -f "$devbox_container_id_file_path"
exit 1
fi
if docker ps --no-trunc --format '{{.ID}}' | grep -q "^${devbox_container_id}\$"; then
echo "==> DevBox container is running."
else
echo "==> DevBox container is not running."
docker start "$devbox_container_id" &>/dev/null || true
sleep 20
fi
if [[ -z "$COMPONENT" ]]; then
COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend" "devsvc" "content" "central_storage" "authentication")
else
COMPONENTS=("$COMPONENT")
fi
# Stop the specified components
for comp in "${COMPONENTS[@]}"; do
case "$comp" in
"mongodb")
echo "==> Stopping MongoDB..."
if [[ -f "${WORKING_HOME}/.mongodb-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.mongodb-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> MongoDB container is not running."
fi
;;
"rabbitmq")
echo "==> Stopping RabbitMQ..."
if [[ -f "${WORKING_HOME}/.rabbitmq-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.rabbitmq-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> RabbitMQ container is not running."
fi
;;
"backend")
echo "==> Stopping backend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> Backend service is not running."
fi
;;
"frontend")
echo "==> Stopping frontend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> Frontend service is not running."
fi
;;
"devsvc" | "content" | "central_storage" | "authentication")
echo "==> Stopping $comp service..."
if [[ -f "${WORKING_HOME}/.${comp}-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.${comp}-instance")
docker stop "$container_id" &>/dev/null || true
else
echo "==> $comp service is not running."
fi
;;
*)
echo "ERROR: Unknown component: $comp"
exit 1
;;
esac
done
# Start the specified components
for comp in "${COMPONENTS[@]}"; do
case "$comp" in
"mongodb")
echo "==> Restarting MongoDB..."
if [[ -f "${WORKING_HOME}/.mongodb-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.mongodb-instance")
docker start "$container_id" &>/dev/null || true
else
echo "==> MongoDB container is not running."
fi
;;
"rabbitmq")
echo "==> Restarting RabbitMQ..."
if [[ -f "${WORKING_HOME}/.rabbitmq-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.rabbitmq-instance")
docker start "$container_id" &>/dev/null || true
else
echo "==> RabbitMQ container is not running."
fi
;;
"backend")
echo "==> Restarting backend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker start "$container_id" &>/dev/null || true
# Start backend service in the container
docker exec -i "$devbox_container_id" bash <<EOF
# Start the backend service
echo "Starting backend service..."
backend_pid=\$(cat /home/.devbox/.backend.pid)
if ps -p "\$backend_pid" > /dev/null; then
echo "Backend service is already running."
else
echo '============================================'
echo 'Start to run start_webapi.sh'
echo '============================================'
pushd /home/.devbox/freeleaps/apps
./start_webapi.sh > /home/.devbox/logs/backend.logs 2>&1 &
BACKEND_PID=\$!
# Save BACKEND_PID to a file \${WORKING_HOME}/.frontend.pid: Stores the process id of frontend process.
echo "\$BACKEND_PID" > /home/.devbox/.backend.pid
echo '============================================'
echo 'Check if the WebAPI service started successfully'
echo '============================================'
sleep 30
# 30 attempts, 5 seconds each, total wait time 2.5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
# Check if \$DEVBOX_BACKEND_PORT exists
if [ -z "\$DEVBOX_BACKEND_PORT" ]; then
echo "WARNING: DEVBOX_BACKEND_PORT is not set."
export DEVBOX_BACKEND_PORT=8002
fi
echo "DEVBOX_BACKEND_PORT: \$DEVBOX_BACKEND_PORT"
echo "Waiting for WebAPI service to become healthy..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_BACKEND_PORT/docs")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Backend Swagger UI is available at \$URL (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Swagger UI to become available... Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 5 # Wait 5 seconds
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: WebAPI failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
fi
EOF
else
echo "==> Backend service is not running."
fi
;;
"frontend")
echo "==> Restarting frontend service..."
if [[ -f "${WORKING_HOME}/.devbox-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.devbox-instance")
docker start "$container_id" &>/dev/null || true
# Start frontend service in the container
docker exec -i "$DEVBOX_NAME" bash <<EOF
# Start the frontend service
# Check if /home/.devbox/.frontend.pid exists
if [ -f /home/.devbox/.frontend.pid ]; then
frontend_pid=\$(cat /home/.devbox/.frontend.pid)
# Check if the frontend service is already running
if ps -p "\$frontend_pid" > /dev/null; then
echo "Frontend service is already running."
exit 0
else
# Remove the frontend.pid file
rm -f /home/.devbox/.frontend.pid
fi
fi
echo '============================================'
echo ' Start frontend service locally'
echo '============================================'
pushd /home/.devbox/freeleaps/frontend
# Check if npm is installed and pnpm is installed and is npm run dev result is generated
if ! command -v npm &>/dev/null; then
echo "ERROR: npm is not installed."
exit 1
fi
if ! command -v pnpm &>/dev/null; then
echo "ERROR: pnpm is not installed."
exit 1
fi
if [ ! -f "package.json" ]; then
echo "ERROR: package.json not found."
exit 1
fi
# Start the frontend service with nohup in order to keep it running after the SSH session is closed
# Save the process ID of the frontend service
nohup npm run dev > /home/.devbox/logs/frontend.logs 2>&1 &
FRONTEND_PID=\$!
echo "npm run dev has been started with PID: \$FRONTEND_PID"
echo "\$FRONTEND_PID" > /home/.devbox/.frontend.pid
# Wait for the frontend service to start
sleep 30
# 30 attempts, 10 seconds each, total wait time 5 minutes
MAX_ATTEMPTS=30
ATTEMPT=0
# Check if \$DEVBOX_FRONTEND_PORT exists
if [ -z "\$DEVBOX_FRONTEND_PORT" ]; then
echo "ERROR: DEVBOX_FRONTEND_PORT is not set."
export DEVBOX_FRONTEND_PORT=5173
fi
echo "Waiting for Frontend service to start..."
while [ \$ATTEMPT -lt \$MAX_ATTEMPTS ]; do
HTTP_CODE=\$(curl -s -o /dev/null -w "%{http_code}" "http://localhost:\$DEVBOX_FRONTEND_PORT/")
# Check HTTP Code 200
if [ "\$HTTP_CODE" -eq 200 ]; then
echo "Frontend is available (HTTP \$HTTP_CODE)"
break
else
echo "Waiting for Frontend to become available... (http://localhost:\$DEVBOX_FRONTEND_PORT), (HTTP \$HTTP_CODE) Attempt \$((ATTEMPT+1))"
ATTEMPT=\$((ATTEMPT+1))
sleep 10
fi
done
if [ \$ATTEMPT -eq \$MAX_ATTEMPTS ]; then
echo "ERROR: Frontend failed to start after \$MAX_ATTEMPTS attempts"
exit 1
fi
EOF
else
echo "==> Frontend service is not running."
fi
;;
"devsvc" | "content" | "central_storage" | "authentication")
echo "==> Restarting $comp service..."
if [[ -f "${WORKING_HOME}/.${comp}-instance" ]]; then
local container_id
container_id=$(cat "${WORKING_HOME}/.${comp}-instance")
docker start "$container_id" &>/dev/null || true
else
echo "==> $comp service is not running."
fi
;;
*)
echo "ERROR: Unknown component: $comp"
exit 1
;;
esac
done
echo "==> DevBox services restarted successfully."
}
# :command.parse_requirements
parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--version | -v)
version_command
exit
;;
--help | -h)
long_usage=yes
devbox_usage
exit
;;
*)
break
;;
esac
done
# :command.environment_variables_filter
env_var_names+=("FREELEAPS_USERNAME")
env_var_names+=("FREELEAPS_PASSWORD")
env_var_names+=("WORKING_HOME")
# :command.command_filter
action=${1:-}
case $action in
-*) ;;
init | i)
action="init"
shift
devbox_init_parse_requirements "$@"
shift $#
;;
deinit | d)
action="deinit"
shift
devbox_deinit_parse_requirements "$@"
shift $#
;;
start | s)
action="start"
shift
devbox_start_parse_requirements "$@"
shift $#
;;
stop | p)
action="stop"
shift
devbox_stop_parse_requirements "$@"
shift $#
;;
status | t)
action="status"
shift
devbox_status_parse_requirements "$@"
shift $#
;;
restart | r)
action="restart"
shift
devbox_restart_parse_requirements "$@"
shift $#
;;
# :command.command_fallback
"")
devbox_usage >&2
exit 1
;;
*)
printf "invalid command: %s\n" "$action" >&2
exit 1
;;
esac
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
}
# :command.parse_requirements
devbox_init_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_init_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="init"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
# :flag.case
--os)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--os' "$2"
shift
shift
else
printf "%s\n" "--os requires an argument: --os OS" >&2
exit 1
fi
;;
# :flag.case
--arch)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--arch' "$2"
shift
shift
else
printf "%s\n" "--arch requires an argument: --arch ARCH" >&2
exit 1
fi
;;
# :flag.case
--devbox-container-name)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devbox-container-name' "$2"
shift
shift
else
printf "%s\n" "--devbox-container-name requires an argument: --devbox-container-name DEVBOX_CONTAINER_NAME" >&2
exit 1
fi
;;
# :flag.case
--devbox-container-port)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devbox-container-port' "$2"
shift
shift
else
printf "%s\n" "--devbox-container-port requires an argument: --devbox-container-port DEVBOX_CONTAINER_PORT" >&2
exit 1
fi
;;
# :flag.case
--devbox-image-repo)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devbox-image-repo' "$2"
shift
shift
else
printf "%s\n" "--devbox-image-repo requires an argument: --devbox-image-repo DEVBOX_IMAGE_REPO" >&2
exit 1
fi
;;
# :flag.case
--devbox-image-name)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devbox-image-name' "$2"
shift
shift
else
printf "%s\n" "--devbox-image-name requires an argument: --devbox-image-name DEVBOX_IMAGE_NAME" >&2
exit 1
fi
;;
# :flag.case
--devbox-image-tag)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devbox-image-tag' "$2"
shift
shift
else
printf "%s\n" "--devbox-image-tag requires an argument: --devbox-image-tag DEVBOX_IMAGE_TAG" >&2
exit 1
fi
;;
# :flag.case
--working-home)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--working-home' "$2"
shift
shift
else
printf "%s\n" "--working-home requires an argument: --working-home WORKING_HOME" >&2
exit 1
fi
;;
# :flag.case
--freeleaps-username)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--freeleaps-username' "$2"
shift
shift
else
printf "%s\n" "--freeleaps-username requires an argument: --freeleaps-username FREELEAPS_USERNAME" >&2
exit 1
fi
;;
# :flag.case
--freeleaps-password)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--freeleaps-password' "$2"
shift
shift
else
printf "%s\n" "--freeleaps-password requires an argument: --freeleaps-password FREELEAPS_PASSWORD" >&2
exit 1
fi
;;
# :flag.case
--use-local-component)
if [[ -n ${2+x} ]]; then
add_arg '--use-local-component' "$2"
shift 2
else
printf "%s\n" "--use-local-component requires an argument: --use-local-component USING_LOCAL_COMPONENT" >&2
exit 1
fi
;;
# :flag.case
--devsvc-image-repo)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devsvc-image-repo' "$2"
shift
shift
else
printf "%s\n" "--devsvc-image-repo requires an argument: --devsvc-image-repo DEVSVC_IMAGE_REPO" >&2
exit 1
fi
;;
# :flag.case
--devsvc-image-name)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devsvc-image-name' "$2"
shift
shift
else
printf "%s\n" "--devsvc-image-name requires an argument: --devsvc-image-name DEVSVC_IMAGE_NAME" >&2
exit 1
fi
;;
# :flag.case
--devsvc-image-tag)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--devsvc-image-tag' "$2"
shift
shift
else
printf "%s\n" "--devsvc-image-tag requires an argument: --devsvc-image-tag DEVSVC_IMAGE_TAG" >&2
exit 1
fi
;;
# :flag.case
--content-image-repo)
if [[ -n ${2+x} ]]; then
add_arg '--content-image-repo' "$2"
shift 2
else
printf "%s\n" "--content-image-repo requires an argument: --content-image-repo FREELEAPS_CONTENT_IMAGE_REPO" >&2
exit 1
fi
;;
# :flag.case
--content-image-name)
if [[ -n ${2+x} ]]; then
add_arg '--content-image-name' "$2"
shift 2
else
printf "%s\n" "--content-image-name requires an argument: --content-image-name FREELEAPS_CONTENT_IMAGE_NAME" >&2
exit 1
fi
;;
# :flag.case
--content-image-tag)
if [[ -n ${2+x} ]]; then
add_arg '--content-image-tag' "$2"
shift 2
else
printf "%s\n" "--content-image-tag requires an argument: --content-image-tag FREELEAPS_CONTENT_IMAGE_TAG" >&2
exit 1
fi
;;
# :flag.case
--central_storage-image-repo)
if [[ -n ${2+x} ]]; then
add_arg '--central_storage-image-repo' "$2"
shift 2
else
printf "%s\n" "--central_storage-image-repo requires an argument: --central_storage-image-repo FREELEAPS_CENTRAL_STORAGE_IMAGE_REPO" >&2
exit 1
fi
;;
# :flag.case
--central_storage-image-name)
if [[ -n ${2+x} ]]; then
add_arg '--central_storage-image-name' "$2"
shift 2
else
printf "%s\n" "--central_storage-image-name requires an argument: --central_storage-image-name FREELEAPS_CENTRAL_STORAGE_IMAGE_NAME" >&2
exit 1
fi
;;
# :flag.case
--central_storage-image-tag)
if [[ -n ${2+x} ]]; then
add_arg '--central_storage-image-tag' "$2"
shift 2
else
printf "%s\n" "--central_storage-image-tag requires an argument: --central_storage-image-tag FREELEAPS_CENTRAL_STORAGE_IMAGE_TAG" >&2
exit 1
fi
;;
# :flag.case
--authentication-image-repo)
if [[ -n ${2+x} ]]; then
add_arg '--authentication-image-repo' "$2"
shift 2
else
printf "%s\n" "--authentication-image-repo requires an argument: --authentication-image-repo FREELEAPS_AUTHENTICATION_IMAGE_REPO" >&2
exit 1
fi
;;
# :flag.case
--authentication-image-name)
if [[ -n ${2+x} ]]; then
add_arg '--authentication-image-name' "$2"
shift 2
else
printf "%s\n" "--authentication-image-name requires an argument: --authentication-image-name FREELEAPS_AUTHENTICATION_IMAGE_NAME" >&2
exit 1
fi
;;
# :flag.case
--authentication-image-tag)
if [[ -n ${2+x} ]]; then
add_arg '--authentication-image-tag' "$2"
shift 2
else
printf "%s\n" "--authentication-image-tag requires an argument: --authentication-image-tag FREELEAPS_AUTHENTICATION_IMAGE_TAG" >&2
exit 1
fi
;;
# :flag.case
--force | -f)
# :flag.case_no_arg
add_arg '--force' '1'
shift
;;
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
# :command.required_flags_filter
if [[ -z "$(get_arg '--freeleaps-username')" ]]; then
printf "missing required flag: --freeleaps-username FREELEAPS_USERNAME\n" >&2
exit 1
fi
if [[ -z "$(get_arg '--freeleaps-password')" ]]; then
printf "missing required flag: --freeleaps-password FREELEAPS_PASSWORD\n" >&2
exit 1
fi
# :command.default_assignments
if [ -z "$(get_arg '--os')" ]; then
add_arg '--os' "auto"
fi
if [ -z "$(get_arg '--arch')" ]; then
add_arg '--arch' "auto"
fi
if [ -z "$(get_arg '--devbox-container-name')" ]; then
add_arg '--devbox-container-name' "devbox"
fi
if [ -z "$(get_arg '--devbox-container-port')" ]; then
add_arg '--devbox-container-port' "22222"
fi
if [ -z "$(get_arg '--devbox-frontend-port')" ]; then
add_arg '--devbox-frontend-port' "5173"
fi
if [ -z "$(get_arg '--devbox-backend-port')" ]; then
add_arg '--devbox-backend-port' "8002"
fi
if [ -z "$(get_arg '--devbox-image-repo')" ]; then
add_arg '--devbox-image-repo' "docker.io/freeleaps"
fi
if [ -z "$(get_arg '--devbox-image-name')" ]; then
add_arg '--devbox-image-name' "devbox_v1"
fi
if [ -z "$(get_arg '--devbox-image-tag')" ]; then
add_arg '--devbox-image-tag' "devbox_local"
fi
if [ -z "$(get_arg '--devsvc-image-tag')" ]; then
add_arg '--devsvc-image-tag' "latest-linux-arm64"
fi
if [ -z "$(get_arg '--content-image-tag')" ]; then
add_arg '--content-image-tag' "latest-linux-arm64"
fi
if [ -z "$(get_arg '--central_storage-image-tag')" ]; then
add_arg '--central_storage-image-tag' "latest-linux-arm64"
fi
if [ -z "$(get_arg '--authentication-image-tag')" ]; then
add_arg '--authentication-image-tag' "latest-linux-arm64"
fi
if [ -z "$(get_arg '--working-home')" ]; then
add_arg '--working-home' "${HOME}/.devbox"
fi
if [ -z "$(get_arg '--use-local-component')" ]; then
add_arg '--use-local-component' "false"
fi
}
# :command.parse_requirements
devbox_deinit_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_deinit_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="deinit"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
# :flag.case
--working-home)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--working-home' "$2"
shift
shift
else
printf "%s\n" "--working-home requires an argument: --working-home WORKING_HOME" >&2
exit 1
fi
;;
# :flag.case
--clear-logs)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--clear-logs' "$2"
shift
shift
else
printf "%s\n" "--clear-logs requires an argument: --clear-logs CLEAR_LOGS" >&2
exit 1
fi
;;
# :flag.case
--clear-repo)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--clear-repo' "$2"
shift
shift
else
printf "%s\n" "--clear-repo requires an argument: --clear-repo CLEAR_REPO" >&2
exit 1
fi
;;
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
# :command.default_assignments
if [ -z "$(get_arg '--working-home')" ]; then
add_arg '--working-home' "${HOME}/.devbox"
fi
if [ -z "$(get_arg '--clear-logs')" ]; then
add_arg '--clear-logs' "false"
fi
if [ -z "$(get_arg '--clear-repo')" ]; then
add_arg '--clear-repo' "false"
fi
}
# :command.parse_requirements
devbox_start_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_start_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="start"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
# :flag.case
--component)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--component' "$2"
shift
shift
else
printf "%s\n" "--component requires an argument: --component COMPONENT" >&2
exit 1
fi
;;
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
}
# :command.parse_requirements
devbox_stop_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_stop_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="stop"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
# :flag.case
--component)
# :flag.case_arg
if [[ -n ${2+x} ]]; then
add_arg '--component' "$2"
shift
shift
else
printf "%s\n" "--component requires an argument: --component COMPONENT" >&2
exit 1
fi
;;
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
}
# :command.parse_requirements
devbox_status_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_status_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="status"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
}
# :command.parse_requirements
devbox_restart_parse_requirements() {
# :command.fixed_flags_filter
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
--help | -h)
long_usage=yes
devbox_restart_usage
exit
;;
*)
break
;;
esac
done
# :command.command_filter
action="restart"
# :command.parse_requirements_while
while [[ $# -gt 0 ]]; do
key="$1"
case "$key" in
-?*)
printf "invalid option: %s\n" "$key" >&2
exit 1
;;
*)
# :command.parse_requirements_case
# :command.parse_requirements_case_simple
printf "invalid argument: %s\n" "$key" >&2
exit 1
;;
esac
done
}
initialize() {
version="1.0.0"
long_usage=""
set -e
# Use the following variables to define the environment variables and input parameters
args_keys=()
args_values=()
deps_keys=()
deps_values=()
# For each environment variable, add a line like the following:
env_var_names=()
input=()
}
# :command.run
run() {
normalize_input "$@"
parse_requirements "${input[@]}"
case "$action" in
"init") devbox_init_command ;;
"deinit") devbox_deinit_command ;;
"start") devbox_start_command ;;
"stop") devbox_stop_command ;;
"status") devbox_status_command ;;
"restart") devbox_restart_command ;;
esac
}
initialize
run "$@"