#!/usr/bin/env bash set -euo pipefail if ! command -v dialog $> /dev/null; then echo \"dialog\" executable missing, please install it... exiting exit 1 fi if ! command -v jq $> /dev/null; then echo \"jq\" executable missing, please install it... exiting exit 1 fi if ! command -v docker $> /dev/null; then echo \"docker\" executable missing, please install it... exiting exit 1 fi set +e docker compose &>/dev/null if [ $? -ne 0 ]; then echo Docker \"compose\" plugin missing, please install it... exiting exit 1 fi set -e export NCURSES_NO_UTF8_ACS=1 get_service_ports() { local folder="$1" ports=$(docker compose -f "$folder"/docker-compose.yml ps --format '{{if index .Publishers 0}}{{range .Publishers}}{{if ne .PublishedPort 0}}{{$.Service}} {{.PublishedPort}} |{{end}}{{end}}{{end}}' | awk NF | tr '\n' ' ') if [[ "$ports" == "" ]]; then if [[ $(docker compose -f "$folder"/docker-compose.yml ps --format '{{.State}}') == "running" ]]; then echo "Running (no ports exposed)" else echo "Not Running" fi else echo "[ ${ports::-3} ]" fi } get_service_status() { local folder="$1" docker compose -f "$folder"/docker-compose.yml ps --format json } # Function to display service menu and execute action perform_service_action() { local folder="$1" service_status=$(get_service_status "$folder") # Define service action options as an array service_actions=() tot_actions=0 service_actions+=("backup" "Backup $folder services") && ((tot_actions+=1)) [ "$service_status" = "" ] && service_actions+=("start" "Start $folder services") && ((tot_actions+=1)) [ "$service_status" != "" ] && service_actions+=("stop" "Stop $folder services") && ((tot_actions+=1)) [ "$service_status" != "" ] && service_actions+=("restart" "Restart $folder services") && ((tot_actions+=1)) [ "$service_status" != "" ] && service_actions+=("logs" "Show $folder services logs") && ((tot_actions+=1)) service_actions+=("update" "Update $folder services image") && ((tot_actions+=1)) # for now commented out shell access, it needs to select the specific container in the service # [ "$service_status" != "" ] && service_actions+=("sh" "Run SH shell in $folder services") && ((tot_actions+=1)) # [ "$service_status" != "" ] && service_actions+=("bash" "Run BASH shell $folder services") && ((tot_actions+=1)) # Get user selection from menu a1=$((tot_actions+7)) a2=$((tot_actions+2)) selected_action=$(dialog --title "Select Action" --menu "What do do on $folder service:" $a1 60 $a2 "${service_actions[@]}" 3>&1 1>&2 2>&3) echo "$selected_action" DC="docker compose -f $folder/docker-compose.yml" # Check exit status and selected action exit_status=$? if [[ $exit_status -eq 1 ]]; then echo "Action cancelled." elif [[ $exit_status -eq 255 ]]; then echo "An error occurred." else # Simulate command execution (replace with actual execution for production use) # You can use libraries like subprocess to execute the command in production if [[ "$selected_action" == "backup" ]]; then echo "Executing: backup.sh $folder" bash backup.sh "$folder" elif [[ "$selected_action" == "start" ]]; then echo "Executing: $DC up -d" $DC up -d elif [[ "$selected_action" == "stop" ]]; then echo "Executing: $DC down" $DC down elif [[ "$selected_action" == "restart" ]]; then echo "Executing: $DC down; $DC up -d" $DC down; $DC up -d elif [[ "$selected_action" == "logs" ]]; then echo "Executing: $DC logs -f" $DC logs -f elif [[ "$selected_action" == "update" ]]; then echo "Executing: $DC down; $DC pull; $DC up -d" $DC down; $DC pull; $DC up -d # these 2 could not work if more than 1 container in docker compose, it needs to select the specific container in the service # TODO elif [[ "$selected_action" == "sh" ]]; then echo "Executing: $DC exec $folder /bin/sh" $DC exec "$folder" /bin/sh elif [[ "$selected_action" == "bash" ]]; then echo "Executing: $DC exec $folder /bin/bash" $DC exec "$folder" /bin/bash fi fi } # Get all docker-compose.yml files in the current directory and one subdirectory # shellcheck disable=SC2207 folders=( $(find . -maxdepth 2 -name 'docker-compose.yml' -print | sed 's/\/docker-compose.yml//' | sort ) ) # Check if any files found if [[ ${#folders[@]} -eq 0 ]]; then dialog --msgbox "Error: No docker-compose.yml files found in current directory or subdirectories." 10 30 exit 1 fi # Loop through folders and build menu options with stripped folder names options=() tot_folders=0 max_length=0 for folder in "${folders[@]}"; do # Remove leading ./ from folder name using parameter expansion ((tot_folders+=1)) folder_name="${folder##*/}" service_ports=$(get_service_ports "$folder") total_length=$(( ${#folder_name} + ${#service_ports} )) [[ "$total_length" -gt "$max_length" ]] && max_length="$total_length" options+=( "$folder_name" "$service_ports" ) done f1=$((tot_folders+7)) f2=$((tot_folders+2)) lenght=$((max_length+22)) # Display menu with folder name (without ./) and service name (without trailing colon) choice=$(dialog --title "Select Service to access Actions" --menu "Services ports shown, if service running:" $f1 $lenght $f2 "${options[@]}" 3>&1 1>&2 2>&3) # Exit status check (user cancellation or error) exit_status=$? if [[ $exit_status -eq 1 ]]; then echo "Selection cancelled." elif [[ $exit_status -eq 255 ]]; then echo "An error occurred." else # Extract selected folder and service name (if selection happened) selected_folder="${choice%% *}" # Call function to display service action menu perform_service_action "$selected_folder" fi