From 40e9367b6f483bed14f15637c421c53e717fcf3a Mon Sep 17 00:00:00 2001 From: abdulhade Date: Tue, 18 Mar 2025 10:17:37 +0300 Subject: [PATCH] Updated the `update_code` function --- Dockerfile | 2 +- scripts/manager.sh | 445 +++++++++++++++++++++++++++++---------------- 2 files changed, 288 insertions(+), 159 deletions(-) diff --git a/Dockerfile b/Dockerfile index a9fa9e2..137e91c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,7 @@ ENV PYTHONUNBUFFERED=1 WORKDIR /app # Install system dependencies required for MySQL and other libraries -# RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y git # default-libmysqlclient-dev \ # build-essential \ # && rm -rf /var/lib/apt/lists/* diff --git a/scripts/manager.sh b/scripts/manager.sh index ba2685b..36e9929 100755 --- a/scripts/manager.sh +++ b/scripts/manager.sh @@ -9,131 +9,153 @@ IMAGE_NAME="db-middleware" CONTAINER_NAME="con-db-middleware" REPO_URL="https://gitea.abdulhade.com/abdulhade/db-middleware.git" +EXECUTION_MESSAGE="NO-RETURN" + build_docker_image() { - docker build -t $IMAGE_NAME . + echo "Building Docker image..." + if docker build -t "$IMAGE_NAME" .; then + echo "Docker image built successfully." + return 0 + else + echo "Failed to build Docker image." + return 1 + fi +} +test() { + echo "I am here" + return 1 +} + +exec_in_container() { + # Returns 0 if the command was successful + echo 0 + local CONTAINER_NAME=$CONTAINER_NAME + local COMMAND="$1" + # Check if the container is running + if ! docker ps --format '{{.Names}}' | grep -q "^$CONTAINER_NAME$"; then + echo "Error: Container '$CONTAINER_NAME' is not running." + return 1 + fi + echo 1 + + + # Execute the command in the container + OUTPUT=$(docker exec "$CONTAINER_NAME" bash -c "$COMMAND" 2>&1) + echo 2 + local EXIT_CODE=$? + echo 3 + # Check if the command succeeded + if [[ $EXIT_CODE -eq 0 ]]; then + echo "$OUTPUT" # Return the output + return 0 + else + echo "Error: Command failed in container '$CONTAINER_NAME' with exit code $EXIT_CODE." + echo "Output: $OUTPUT" + return $EXIT_CODE + fi } set_up_scripts() { - # Copy scripts from the code directory to the app directory - cp "$CODE_DIR/scripts/"* "$APP_DIR/scripts/" + echo "Setting up scripts..." - # Give execution permission to all scripts - chmod +x "$APP_DIR/scripts/"* + # Copy scripts + if ! cp "$CODE_DIR/scripts/"* "$APP_DIR/scripts/"; then + echo "Failed to copy scripts." + return 1 + fi + # Give execution permission + if ! chmod +x "$APP_DIR/scripts/"*; then + echo "Failed to set execution permissions." + return 1 + fi + + # Create ~/.local/bin if it doesn't exist mkdir -p "$HOME/.local/bin" - ln -s "$APP_DIR/scripts/manager.sh" "$HOME/.local/bin/db-middleware" - export PATH="$HOME/.local/bin:$PATH" - source ~/.bashrc + + # Create symlink + if ! ln -sf "$APP_DIR/scripts/manager.sh" "$HOME/.local/bin/db-middleware"; then + echo "Failed to create symlink." + # TODO Here we should handle the case of having the symlink created previously. + return 1 + fi + + # Update PATH + if ! grep -q "$HOME/.local/bin" ~/.bashrc; then + echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc + fi + + # Reload bashrc + if ! source ~/.bashrc; then + echo "Failed to reload ~/.bashrc." + return 1 + fi + + echo "Scripts set up successfully." + return 0 } -pull_clone_repo() { - local UPDATED=0 - - # Check if the code directory exists - if [[ ! -d "$CODE_DIR" ]]; then - echo "Creating code directory at $CODE_DIR..." - fi - - mkdir -p "$APP_DIR/{code,configs,scripts}" - - # Navigate to the code directory - cd "$CODE_DIR" || { echo "Failed to navigate to $CODE_DIR"; exit 1; } - - # Check if the directory is empty - if [[ -z "$(ls -A $CODE_DIR)" ]]; then - echo "Directory is empty. Cloning repository..." - git clone "$REPO_URL" . - echo "Repository cloned successfully." - UPDATED=1 # Newly cloned, so changes are "new" - else - # Check if the directory contains a Git repository - if [[ -d ".git" ]]; then - echo "Directory contains a Git repository." - - # Fetch the latest changes from the remote repository - git fetch origin - - # Get the local and remote HEAD commit hashes - LOCAL_HEAD=$(git rev-parse HEAD) - REMOTE_HEAD=$(git rev-parse origin/main) # Replace 'main' with your branch name - - # Compare the commit hashes - if [[ "$LOCAL_HEAD" != "$REMOTE_HEAD" ]]; then - echo "Repository has new changes. Pulling latest changes..." - git pull "$REPO_URL" - echo "Repository updated successfully." - UPDATED=1 # Changes were pulled - else - echo "Repository is already up to date." - UPDATED=0 # No changes - fi - else - echo "Directory is not empty and does not contain a Git repository." - echo "Please ensure the directory is empty or contains a valid Git repository." - echo " > $APP_DIR" - exit 1 - fi - fi - - # Check if the operation was successful - if [[ $? -eq 0 ]]; then - echo "Repository setup completed successfully." - else - echo "Failed to set up the repository." - exit 1 - fi - - # Return the UPDATED value - return $UPDATED -} - -# Function to load the config file load_config() { if [[ -f "$CONFIG_FILE" ]]; then - source "$CONFIG_FILE" - LOADED_CONFIG=1 + if source "$CONFIG_FILE"; then + LOADED_CONFIG=1 + echo "Config file loaded successfully." + return 0 + else + echo "Failed to load config file." + return 1 + fi else echo "Config file not found: $CONFIG_FILE" - exit 1 + return 1 fi } show_config() { - if [[ $LOADED_CONFIG -eq 0 ]]; then - echo "Didn't load config" + echo "Config not loaded. Please load the config file first." + return 1 fi echo "Current Config:" - echo "CONTAINER_NAME: $CONTAINER_NAME" - echo "API_PORT: $API_PORT" - echo "HAS_LOCAL_DBS: $HAS_LOCAL_DBS" - + echo "CONTAINER_NAME: ${CONTAINER_NAME:-Not set}" + echo "API_PORT: ${API_PORT:-Not set}" + echo "HAS_LOCAL_DBS: ${HAS_LOCAL_DBS:-Not set}" local RUN_COMMAND="docker run --name $CONTAINER_NAME" if [[ $HAS_LOCAL_DBS -eq 1 ]]; then RUN_COMMAND+=" --network host" fi - RUN_COMMAND+=" -p $API_PORT:8080 $IMAGE_NAME" - echo "$RUN_COMMAND" + RUN_COMMAND+=" -p ${API_PORT:-8080}:8080 $IMAGE_NAME" + echo "Run Command: $RUN_COMMAND" - + return 0 } convert_ports_to_docker_args() { local ports="$1" local docker_args="" + if [[ -z "$ports" ]]; then + echo "No ports provided." + return 1 + fi + # Split the ports by comma and trim whitespace IFS=',' read -r -a port_array <<< "$ports" # Loop through the ports and format them as Docker arguments for port in "${port_array[@]}"; do port=$(echo "$port" | xargs) # Trim whitespace + if [[ ! "$port" =~ ^[0-9]+$ ]]; then + echo "Invalid port: $port" + return 1 + fi docker_args+=" -p $port:$port" done echo "$docker_args" + return 0 } install() { @@ -143,9 +165,15 @@ install() { echo "+------------------------------+" echo - cd "$CODE_DIR" - - build_docker_image + if ! cd "$CODE_DIR"; then + echo "Failed to navigate to $CODE_DIR." + return 1 + fi + + if ! build_docker_image; then + echo "Failed to build Docker image." + return 1 + fi echo echo "+----------------------------------------+" @@ -156,22 +184,116 @@ install() { echo " >>> db-middleware start" echo "- Or directly by running the docker container:" echo " >>> docker run $IMAGE_NAME -p : -v /path/to/app/directory/" + return 0 +} + +pull_clone_repo() { + local UPDATED=-1 # Default: No changes + + echo "Setting up repository..." + + # Create directories if they don't exist + mkdir -p "$APP_DIR/{code,configs,scripts}" + + # Navigate to the code directory + if ! cd "$CODE_DIR"; then + echo "Failed to navigate to $CODE_DIR." + return 1 # Error + fi + + # Check if the directory is empty + if [[ -z "$(ls -A $CODE_DIR)" ]]; then + echo "Directory is empty. Cloning repository..." + if ! git clone "$REPO_URL" .; then + echo "Failed to clone repository." + return 1 # Error + fi + echo "Repository cloned successfully." + UPDATED=0 # Changes were applied + else + # Check if the directory contains a Git repository + if [[ -d ".git" ]]; then + echo "Directory contains a Git repository." + + # Fetch the latest changes + if ! git fetch origin; then + echo "Failed to fetch changes from remote." + return 1 # Error + fi + + # Get the local and remote HEAD commit hashes + LOCAL_HEAD=$(git rev-parse HEAD) + REMOTE_HEAD=$(git rev-parse origin/main) + exec_in_container "git rev-parse HEAD" + local COMMIT_HASH=$? + + if [[ $COMMIT_HASH -eq 0 ]]; then + echo "Commit hash in container: $COMMIT_HASH" + else + echo "Failed to get commit hash from container." + fi + + # Compare the commit hashes + if [[ "$LOCAL_HEAD" != "$REMOTE_HEAD" ]]; then + echo "Repository has new changes. Pulling latest changes..." + if ! git pull "$REPO_URL"; then + echo "Failed to pull changes." + return 1 # Error + fi + echo "Repository updated successfully." + UPDATED=0 # Changes were applied + else + echo "Repository is already up to date." + UPDATED=-1 # No changes + # echo $UPDATED + fi + else + echo "Directory is not empty and does not contain a Git repository." + echo "Please ensure the directory is empty or contains a valid Git repository." + return 1 # Error + fi + fi + + echo "Repository setup completed successfully: $UPDATED." + + return $UPDATED # -1 = No changes, 0 = Changes applied } update_code() { + echo + echo "+-------------------------+" + echo "| Checking for updates... |" + echo "+-------------------------+" + echo + pull_clone_repo local UPDATED=$? - if [[ $UPDATED -eq 1 ]]; then - echo "Changes were detected and applied." - else - echo "No changes detected." - fi + case $UPDATED in - return $UPDATED + -1) + echo "No changes detected." + return -1 # No changes + ;; + 255) # 255 is -1, because Bash return codes are unsigned 8-bit integer, limited to the range 0 to 255. + echo "No changes detected." + return -1 # No changes + ;; + -0) + echo "Changes were detected and applied." + return 0 # Changes applied + ;; + 1) + echo "Failed to update or clone repository." + return 1 # Error + ;; + *) + echo "Wrong return code: \`$UPDATED\` from pull_clone_repo." + return 1 + ;; + esac } -# Function for the "upgrade" command upgrade() { echo echo "+-----------------------------+" @@ -180,104 +302,111 @@ upgrade() { echo update_code - local UPDATED=$? + local UPDATE_RESULT=$? - if [[ $UPDATED -eq 1 ]]; then - echo - echo "+--------------------------------+" - echo "| Rebuilding the Docker Image... |" - echo "+--------------------------------+" - echo + case $UPDATE_RESULT in + # 255 is -1, because Bash return codes are unsigned 8-bit integer, limited to the range 0 to 255. + -1|255) + echo + echo "+------------------------------------------+" + echo "| No changes detected. Skipping upgrade... |" + echo "+------------------------------------------+" + echo + ;; + 0) + echo + echo "+--------------------------------+" + echo "| Rebuilding the Docker Image... |" + echo "+--------------------------------+" + echo - build_docker_image + if ! build_docker_image; then + echo "Failed to rebuild Docker image." + return 1 # Error + fi - set_up_scripts - - echo - echo "+---------------------------------------+" - echo "| Upgraded the Middleware Successfully! |" - echo "+---------------------------------------+" - echo - - else - echo - echo "+-------------------------------------+" - echo "| No need to rebuild the Docker Image |" - echo "+-------------------------------------+" - echo - fi + if ! set_up_scripts; then + echo "Failed to set up scripts." + return 1 # Error + fi + echo + echo "+---------------------------------------+" + echo "| Upgraded the Middleware Successfully! |" + echo "+---------------------------------------+" + echo + ;; + 1) + echo "Failed to update code. Upgrade aborted." + return 1 # Error + ;; + esac + return 0 } -# Function for the "status" command + status() { - echo "Running the 'status' function." - docker - # Add your status-checking logic here + echo "Checking container status..." + if docker ps --filter "name=$CONTAINER_NAME" --format "{{.Status}}"; then + return 0 + else + echo "Failed to check container status." + return 1 + fi } -# Function for the "start" command start() { echo "+---------------------------+" echo "| Starting the Container... |" echo "+---------------------------+" echo - docker run db-middleware + + if ! docker run --name "$CONTAINER_NAME" -p "${API_PORT:-8080}:8080" "$IMAGE_NAME"; then + echo "Failed to start container." + return 1 + fi + + return 0 } -# Function for the "stop" command stop() { - echo "Running the 'stop' function." - # Add your stop logic here + echo "Stopping the container..." + if docker stop "$CONTAINER_NAME"; then + echo "Container stopped successfully." + return 0 + else + echo "Failed to stop container." + return 1 + fi } -# Function to display usage instructions usage() { - echo "Usage: $0 {install|upgrade|status|start|stop}" + echo "Usage: $0 {install|upgrade|update_code|status|start|stop|show_config}" exit 1 } -# Main script logic + main() { # Check if an argument is provided if [[ $# -eq 0 ]]; then usage fi + if ! load_config; then + echo "Failed to load config. Exiting." + exit 1 + fi # Handle the argument case "$1" in - install) - install - ;; - update_code) - load_config - update_code - ;; - upgrade) - load_config - upgrade - ;; - status) - load_config - status - ;; - start) - load_config - start - ;; - show_config) - load_config - show_config - ;; - stop) - load_config - stop - ;; - *) - echo "Invalid argument: $1" - usage - ;; + install) install ;; + update_code) update_code ;; + upgrade) upgrade ;; + status) status ;; + start) start ;; + show_config) show_config ;; + stop) stop ;; + *) echo "Invalid argument: $1"; usage ;; esac }