diff --git a/devbox/devbox.local/devbox b/devbox/devbox.local/devbox index f8b6cbe..19ae0dd 100644 --- a/devbox/devbox.local/devbox +++ b/devbox/devbox.local/devbox @@ -62,6 +62,7 @@ devbox_usage() { fi } + # :command.usage devbox_init_usage() { if [[ -n $long_usage ]]; then @@ -249,13 +250,214 @@ devbox_init_usage() { # :command.usage_examples printf "%s\n" "Examples:" - printf " devbox init --os=linux --arch=amd64 --freeleaps-username alice\n --freeleaps-password secret\n" + 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, payment, 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, payment, 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() { @@ -430,11 +632,108 @@ check_docker_running() { return 1 } +start_local_mongodb() { + echo "==> Starting MongoDB service..." + echo "Step 3. [INFO] Starting MongoDB container..." + + MONGO_CONTAINER_NAME="freeleaps2-mongo" + 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") + 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..." +} + # :command.command_functions # :command.function devbox_init_command() { - # src/init_command.sh #!/usr/bin/env bash echo "==> [INIT] Starting DevBox environment initialization..." echo @@ -517,7 +816,7 @@ devbox_init_command() { echo "==> Checking parameters..." for component in "${components[@]}"; do echo "==> Checking ${component} image repo...value: ${args["${component}_image_repo"]}" - # if ${args["${component}_image_repo"]} is not empty, then set is_pull_all_components to false + # if any component image repo is provided, then don't pull all components if [[ -n "${args["${component}_image_repo"]}" ]]; then is_pull_all_components=false break @@ -603,9 +902,9 @@ devbox_init_command() { # 3.2 Check disk space local free_space_kb free_space_kb="$(df -Pk "$HOME" | awk 'END{print $4}')" - # 若无法获取或小于 1GB (1048576 KB),报错 - if [[ -z "$free_space_kb" || $free_space_kb -lt 1048576 ]]; then - echo "ERROR: Insufficient disk space (need >1GB)." + # 若无法获取或小于 10GB (10485760 KB),报错 + if [[ -z "$free_space_kb" || $free_space_kb -lt 10485760 ]]; then + echo "ERROR: Insufficient disk space (need >10GB)." exit 1 fi @@ -785,94 +1084,10 @@ if [[ "${USE_LOCAL_COMPONENT,,}" == "true" ]]; then # 3.Create and start MongoDB container echo "Step 3. [INFO] Starting MongoDB container..." - MONGO_CONTAINER_NAME="freeleaps2-mongo" - 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") - 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 - - echo '============================================' - - 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 "Step 4. [INFO] Starting MongoDB container..." + start_local_mongodb # 4. Pull and start RabbitMQ container - echo "Step 4. [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 - echo "==> Starting RabbitMQ container..." - 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 "Step 5. [INFO] Starting RabbitMQ container..." + start_local_rabbitMQ else echo '============================================' echo ' ===> Using online components for Freeleaps services.' @@ -1032,8 +1247,10 @@ echo '============================================' echo 'Start to run start_webapi.sh' echo '============================================' ./start_webapi.sh > /home/.devbox/logs/backend.logs 2>&1 & -WEBAPI_PID=\$! +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' @@ -1084,17 +1301,17 @@ npm run build npm run format # Start the frontend service with nohup in order to keep it running after the SSH session is closed nohup npm run dev > /home/.devbox/logs/frontend.logs > /dev/null 2>&1 & - # Save the process ID of the frontend service -DEV_PID=$! +FRONTEND_PID=$! -echo "npm run dev has been started with PID: \$DEV_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 120 +sleep 30 # 30 attempts, 10 seconds each, total wait time 5 minutes MAX_ATTEMPTS=30 @@ -1132,15 +1349,760 @@ EOF echo "===========================================================" echo "DevBox init completed successfully!" echo " DevBox container ID: $container_id" - [[ -f "${WORKING_HOME}/.devsvc-instance" ]] && echo " devsvc container ID: $(cat "${WORKING_HOME}/.devsvc-instance")" + [[ -f "${WORKING_HOME}/.devbox-instance" ]] && echo " devbox container ID: $(cat "${WORKING_HOME}/.devbox-instance")" echo " Repository cloned to: $repo_dir" 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="${args['--working-home']:-${HOME}/.devbox}" + local CLEAR_LOGS="${args['--clear-logs']:-false}" + local CLEAR_REPO="${args['--clear-repo']:-false}" + local FORCE="${args['--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 + + # 停止并删除容器等 + 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" + fi + + echo "==> DevBox deinitialization completed." +} + +# :command.function +devbox_start_command() { + + local COMPONENT="${args['--component']}" + local WORKING_HOME="${args['--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..." + + # 检查 DevBox 容器的状态 + if ! docker ps --no-trunc --format '{{.ID}}' | grep -q "^${devbox_container_id}\$"; then + echo "==> DevBox container is not running, starting 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 [[ -z "$COMPONENT" ]]; then + COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend") + else + COMPONENTS=("$COMPONENT") + fi + + # 启动指定的组件 + 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..." + # 启动容器 + 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..." + # 启动容器 + 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 + +backend_pid=\$(cat /home/.devbox/.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 + 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) + + # 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 > /dev/null 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 + ;; + *) + 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="${args['--component']}" + local WORKING_HOME="${args['--working-home']:-${HOME}/.devbox}" + + echo "==> Stopping DevBox services..." + + # If the DevBox container is not running, exit + if [[ -z "$COMPONENT" ]]; then + COMPONENTS=("mongodb" "rabbitmq" "backend" "frontend") + 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 + ;; + *) + 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="${args['--component']}" + local WORKING_HOME="${args['--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") + + echo "==> Checking DevBox services status..." + + # 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") + 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 "==> MongoDB container is running." + else + echo "==> MongoDB container is not running." + fi + else + echo "==> 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 "==> RabbitMQ container is running." + else + echo "==> RabbitMQ container is not running." + fi + else + echo "==> 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 + echo "==> Backend service is running." + else + echo "==> Backend service is not running." + fi + else + echo "==> Backend service is not running." + 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 + echo "==> Frontend service is running." + else + echo "==> Frontend service is not running." + fi + else + echo "==> Frontend service 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="${args['--component']}" + local WORKING_HOME="${args['--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") + else + COMPONENTS=("$COMPONENT") + fi + + echo "==> Restarting DevBox services..." + + # 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 + ;; + *) + 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 < /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 "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 + + 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 < /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 > /dev/null 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 + ;; + *) + echo "ERROR: Unknown component: $comp" + exit 1 + ;; + esac + done + + echo "==> DevBox services restarted successfully." +} + # :command.parse_requirements parse_requirements() { # :command.fixed_flags_filter @@ -1184,6 +2146,41 @@ 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 @@ -1220,6 +2217,7 @@ parse_requirements() { } + # :command.parse_requirements devbox_init_parse_requirements() { # :command.fixed_flags_filter @@ -1615,17 +2613,315 @@ devbox_init_parse_requirements() { [[ -n ${args['--devbox-image-repo']:-} ]] || args['--devbox-image-repo']="docker.io/freeleaps" [[ -n ${args['--devbox-image-name']:-} ]] || args['--devbox-image-name']="devbox_v1" [[ -n ${args['--devbox-image-tag']:-} ]] || args['--devbox-image-tag']="devbox_local" - [[ -n ${args['--devsvc-image-tag']:-} ]] || args['--devsvc-image-tag']="latest-linux-amd64" - [[ -n ${args['--payment-image-tag']:-} ]] || args['--payment-image-tag']="latest-linux-amd64" - [[ -n ${args['--content-image-tag']:-} ]] || args['--content-image-tag']="latest-linux-amd64" - [[ -n ${args['--central_storage-image-tag']:-} ]] || args['--central_storage-image-tag']="latest-linux-amd64" - [[ -n ${args['--authentication-image-tag']:-} ]] || args['--authentication-image-tag']="latest-linux-amd64" + [[ -n ${args['--devsvc-image-tag']:-} ]] || args['--devsvc-image-tag']="latest-linux-arm64" + [[ -n ${args['--payment-image-tag']:-} ]] || args['--payment-image-tag']="latest-linux-arm64" + [[ -n ${args['--content-image-tag']:-} ]] || args['--content-image-tag']="latest-linux-arm64" + [[ -n ${args['--central_storage-image-tag']:-} ]] || args['--central_storage-image-tag']="latest-linux-arm64" + [[ -n ${args['--authentication-image-tag']:-} ]] || args['--authentication-image-tag']="latest-linux-arm64" [[ -n ${args['--working-home']:-} ]] || args['--working-home']="${HOME}/.devbox" [[ -n ${args['--use-local-component']:-} ]] || args['--use-local-component']="true" } + +# :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 + args['--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 + args['--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 + args['--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 + [[ -n ${args['--working-home']:-} ]] || args['--working-home']="${HOME}/.devbox" + [[ -n ${args['--clear-logs']:-} ]] || args['--clear-logs']="true" + [[ -n ${args['--clear-repo']:-} ]] || args['--clear-repo']="false" + +} + +# :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 + args['--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 + args['--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 + +} + # :command.initialize initialize() { version="1.0.0" @@ -1647,8 +2943,12 @@ run() { 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 "$@"