397 lines
9.3 KiB
Bash
Executable File
397 lines
9.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Core functions for the docker-compose plugin
|
|
|
|
# Set strict mode
|
|
set -eo pipefail
|
|
[[ $DOKKU_TRACE ]] && set -x
|
|
|
|
# Import dokku functions
|
|
if [[ -f "/var/lib/dokku/core-plugins/available/common/functions" ]]; then
|
|
source /var/lib/dokku/core-plugins/available/common/functions
|
|
fi
|
|
|
|
# Set default values if not already set
|
|
PLUGIN_NAME=${PLUGIN_NAME:-docker-compose}
|
|
PLUGIN_PATH=${PLUGIN_PATH:-$(cd "$(dirname "${BASH_SOURCE[0]}/..")" && pwd)}
|
|
PLUGIN_DATA_ROOT=${PLUGIN_DATA_ROOT:-"/var/lib/dokku/data/$PLUGIN_NAME"}
|
|
PLUGIN_LOG_FILE=${PLUGIN_LOG_FILE:-"$PLUGIN_DATA_ROOT/logs/plugin.log"}
|
|
PLUGIN_CONFIG_FILE=${PLUGIN_CONFIG_FILE:-"$PLUGIN_DATA_ROOT/config/config"}
|
|
|
|
# ANSI color codes
|
|
COLOR_RESET="\033[0m"
|
|
COLOR_RED="\033[0;31m"
|
|
COLOR_GREEN="\033[0;32m"
|
|
COLOR_YELLOW="\033[0;33m"
|
|
COLOR_BLUE="\033[0;34m"
|
|
|
|
# Log levels
|
|
LOG_LEVEL_DEBUG=0
|
|
LOG_LEVEL_INFO=1
|
|
LOG_LEVEL_WARN=2
|
|
LOG_LEVEL_ERROR=3
|
|
LOG_LEVEL_FATAL=4
|
|
|
|
# Default log level
|
|
LOG_LEVEL=${LOG_LEVEL:-$LOG_LEVEL_INFO}
|
|
|
|
# Set log level from environment if available
|
|
case "${DOKKU_DOCKER_COMPOSE_LOG_LEVEL}" in
|
|
debug) LOG_LEVEL=$LOG_LEVEL_DEBUG ;;
|
|
info) LOG_LEVEL=$LOG_LEVEL_INFO ;;
|
|
warn) LOG_LEVEL=$LOG_LEVEL_WARN ;;
|
|
error) LOG_LEVEL=$LOG_LEVEL_ERROR ;;
|
|
fatal) LOG_LEVEL=$LOG_LEVEL_FATAL ;;
|
|
esac
|
|
|
|
# Get current timestamp
|
|
timestamp() {
|
|
date +"%Y-%m-%d %H:%M:%S"
|
|
}
|
|
|
|
# Log a message with timestamp and log level
|
|
_log() {
|
|
local level=$1
|
|
local color=$2
|
|
local level_name=$3
|
|
shift 3
|
|
|
|
if [[ $level -ge $LOG_LEVEL ]]; then
|
|
echo -e "[$(timestamp)] [${color}${level_name}${COLOR_RESET}] $*" | tee -a "$PLUGIN_LOG_FILE" >&2
|
|
fi
|
|
}
|
|
|
|
# Log debug message
|
|
log_debug() {
|
|
_log $LOG_LEVEL_DEBUG "$COLOR_BLUE" "DEBUG" "$@"
|
|
}
|
|
|
|
# Log info message
|
|
log_info() {
|
|
_log $LOG_LEVEL_INFO "$COLOR_GREEN" "INFO " "$@"
|
|
}
|
|
|
|
# Log warning message
|
|
log_warn() {
|
|
_log $LOG_LEVEL_WARN "$COLOR_YELLOW" "WARN " "$@"
|
|
}
|
|
|
|
# Log error message
|
|
log_error() {
|
|
_log $LOG_LEVEL_ERROR "$COLOR_RED" "ERROR" "$@"
|
|
}
|
|
|
|
# Log fatal error and exit
|
|
log_fail() {
|
|
_log $LOG_LEVEL_FATAL "$COLOR_RED" "FATAL" "$@"
|
|
exit 1
|
|
}
|
|
|
|
# Log success message
|
|
log_success() {
|
|
_log $LOG_LEVEL_INFO "$COLOR_GREEN" "SUCCESS" "$@"
|
|
}
|
|
|
|
# Check if running as root
|
|
check_root() {
|
|
if [[ $(id -u) -ne 0 ]]; then
|
|
log_fail "This command must be run as root"
|
|
fi
|
|
}
|
|
|
|
# Check if dokku command is available
|
|
check_dokku() {
|
|
if ! command -v dokku >/dev/null 2>&1; then
|
|
log_fail "Dokku is not installed or not in PATH"
|
|
fi
|
|
}
|
|
|
|
# Load plugin configuration
|
|
load_config() {
|
|
if [[ -f "$PLUGIN_CONFIG_FILE" ]]; then
|
|
# shellcheck source=/dev/null
|
|
source "$PLUGIN_CONFIG_FILE"
|
|
fi
|
|
}
|
|
|
|
# Save plugin configuration
|
|
save_config() {
|
|
mkdir -p "$(dirname "$PLUGIN_CONFIG_FILE")"
|
|
local config
|
|
config=$(declare -p | grep '^declare -x DOKKU_DOCKER_COMPOSE_' | sed 's/^declare -x //')
|
|
echo "$config" > "$PLUGIN_CONFIG_FILE"
|
|
chmod 600 "$PLUGIN_CONFIG_FILE"
|
|
}
|
|
|
|
# Show help
|
|
show_help() {
|
|
cat <<EOF
|
|
Usage: dokku docker-compose:COMMAND [OPTIONS] [ARGS]...
|
|
|
|
Manage Docker Compose deployments in Dokku
|
|
|
|
Commands:
|
|
help, --help, -h Show this help message
|
|
version, --version Show version information
|
|
import Import a Docker Compose file
|
|
plugin:install Install the plugin
|
|
plugin:uninstall Uninstall the plugin
|
|
|
|
Import Options:
|
|
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
|
|
-p, --project NAME Specify an alternate project name (default: directory name)
|
|
--dry-run Show what would be done without making any changes
|
|
-v, --verbose Show more detailed output
|
|
-q, --quiet Suppress output
|
|
|
|
Examples:
|
|
# Import default docker-compose.yml in current directory
|
|
dokku docker-compose:import
|
|
|
|
# Import specific compose file
|
|
dokku docker-compose:import -f docker-compose.prod.yml
|
|
|
|
# Dry run to see what would be created
|
|
dokku docker-compose:import --dry-run
|
|
|
|
# Show version
|
|
dokku docker-compose:version
|
|
EOF
|
|
}
|
|
|
|
# Show version information
|
|
show_version() {
|
|
local version_file="${PLUGIN_PATH}/VERSION"
|
|
if [[ -f "$version_file" ]]; then
|
|
echo "dokku-docker-compose version $(cat "$version_file")"
|
|
else
|
|
echo "dokku-docker-compose version unknown (development)"
|
|
fi
|
|
}
|
|
|
|
# Initialize the plugin environment
|
|
initialize_environment() {
|
|
# Create necessary directories
|
|
mkdir -p "$PLUGIN_DATA_ROOT/logs"
|
|
mkdir -p "$PLUGIN_DATA_ROOT/config"
|
|
|
|
# Set up log file
|
|
touch "$PLUGIN_LOG_FILE"
|
|
chmod 666 "$PLUGIN_LOG_FILE"
|
|
|
|
# Load configuration
|
|
load_config
|
|
|
|
# Set default configuration if not set
|
|
DOKKU_DOCKER_COMPOSE_LOG_LEVEL=${DOKKU_DOCKER_COMPOSE_LOG_LEVEL:-info}
|
|
DOKKU_DOCKER_COMPOSE_MAX_RETRIES=${DOKKU_DOCKER_COMPOSE_MAX_RETRIES:-3}
|
|
DOKKU_DOCKER_COMPOSE_TIMEOUT=${DOKKU_DOCKER_COMPOSE_TIMEOUT:-300}
|
|
|
|
# Save configuration
|
|
save_config
|
|
|
|
log_debug "Plugin environment initialized"
|
|
}
|
|
|
|
# Clean up plugin resources
|
|
cleanup_plugin() {
|
|
log_info "Cleaning up $PLUGIN_NAME plugin..."
|
|
# Add cleanup logic here
|
|
log_success "$PLUGIN_NAME plugin cleaned up successfully"
|
|
}
|
|
|
|
# Logging functions
|
|
log() {
|
|
echo "$@" >&2
|
|
}
|
|
|
|
error() {
|
|
log " ! $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
warn() {
|
|
log " ! WARNING: $*" >&2
|
|
}
|
|
|
|
info() {
|
|
[[ $QUIET ]] || log "-----> $*"
|
|
}
|
|
|
|
# Version checking
|
|
check_dokku_version() {
|
|
local required_version="${1:-0.30.0}"
|
|
local current_version
|
|
current_version=$(dokku --version | head -n 1 | cut -d' ' -f3)
|
|
|
|
if [[ "$(printf "%s\n%s" "$required_version" "$current_version" | sort -V | head -n1)" != "$required_version" ]]; then
|
|
error "Dokku version $required_version or higher is required. Current version: $current_version"
|
|
fi
|
|
}
|
|
|
|
# Argument parsing
|
|
parse_args() {
|
|
local args=("$@")
|
|
local i=0
|
|
|
|
while [[ $i -lt ${#args[@]} ]]; do
|
|
case "${args[$i]}" in
|
|
-f|--file)
|
|
((i++))
|
|
COMPOSE_FILE="${args[$i]}"
|
|
;;
|
|
-p|--project)
|
|
((i++))
|
|
PROJECT_NAME="${args[$i]}"
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=true
|
|
;;
|
|
-v|--verbose)
|
|
set -x
|
|
;;
|
|
-q|--quiet)
|
|
QUIET=true
|
|
;;
|
|
*)
|
|
# Handle non-flag arguments
|
|
if [[ -z "$COMMAND" ]]; then
|
|
COMMAND="${args[$i]}"
|
|
else
|
|
error "Unknown argument: ${args[$i]}"
|
|
fi
|
|
;;
|
|
esac
|
|
((i++))
|
|
done
|
|
}
|
|
|
|
# Check if a command exists
|
|
command_exists() {
|
|
command -v "$1" >/dev/null 2>&1
|
|
}
|
|
|
|
# Check if a file exists and is readable
|
|
file_exists() {
|
|
[[ -r "$1" ]]
|
|
}
|
|
|
|
# Get the project directory
|
|
get_project_dir() {
|
|
echo "${DOKKU_DOCKER_COMPOSE_PROJECT_DIR:-$(pwd)}"
|
|
}
|
|
|
|
# Get the compose file path
|
|
get_compose_file() {
|
|
local project_dir="$(get_project_dir)"
|
|
echo "${COMPOSE_FILE:-${project_dir}/docker-compose.yml}"
|
|
}
|
|
|
|
# Validate compose file
|
|
validate_compose_file() {
|
|
local compose_file="$(get_compose_file)"
|
|
|
|
if ! file_exists "$compose_file"; then
|
|
error "Compose file not found: $compose_file"
|
|
fi
|
|
|
|
# Check if docker-compose or docker compose is available
|
|
if ! command_exists docker-compose && ! command_exists docker compose; then
|
|
error "Neither 'docker-compose' nor 'docker compose' command found"
|
|
fi
|
|
|
|
# Validate compose file syntax
|
|
if command_exists docker-compose; then
|
|
docker-compose -f "$compose_file" config -q || error "Invalid compose file: $compose_file"
|
|
else
|
|
docker compose -f "$compose_file" config -q || error "Invalid compose file: $compose_file"
|
|
fi
|
|
}
|
|
|
|
# Main entry point
|
|
main() {
|
|
# Ensure dokku is available
|
|
if ! command_exists dokku; then
|
|
error "Dokku is not installed or not in PATH"
|
|
fi
|
|
|
|
# Check dokku version
|
|
check_dokku_version "0.30.0"
|
|
|
|
# Parse arguments
|
|
parse_args "$@"
|
|
|
|
# Execute command
|
|
case "$COMMAND" in
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
version|--version|-v)
|
|
show_version
|
|
;;
|
|
import)
|
|
validate_compose_file
|
|
import_compose_file
|
|
;;
|
|
*)
|
|
error "Unknown command: $COMMAND"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Import compose file (stub for now)
|
|
import_compose_file() {
|
|
local compose_file="$(get_compose_file)"
|
|
info "Importing compose file: $compose_file"
|
|
|
|
if [[ -n "$DRY_RUN" ]]; then
|
|
info "Dry run: Would import $compose_file"
|
|
return 0
|
|
fi
|
|
|
|
# Actual import logic will be implemented here
|
|
info "Import functionality coming soon!"
|
|
}
|
|
|
|
# Show help
|
|
show_help() {
|
|
cat <<EOF
|
|
Usage: dokku docker-compose:COMMAND [options]
|
|
|
|
Manage Docker Compose deployments in Dokku.
|
|
|
|
Commands:
|
|
import [path] Import a docker-compose.yml file
|
|
help Show this help message
|
|
version Show version information
|
|
|
|
Options:
|
|
-f, --file FILE Specify an alternate compose file (default: docker-compose.yml)
|
|
-p, --project NAME Specify an alternate project name (default: directory name)
|
|
--dry-run Show what would be created without making changes
|
|
-v, --verbose Increase verbosity
|
|
-q, --quiet Suppress output
|
|
|
|
Examples:
|
|
# Import default docker-compose.yml in current directory
|
|
dokku docker-compose:import
|
|
|
|
# Import specific compose file
|
|
dokku docker-compose:import -f docker-compose.prod.yml
|
|
|
|
# Dry run to see what would be created
|
|
dokku docker-compose:import --dry-run
|
|
EOF
|
|
}
|
|
|
|
# Show version
|
|
show_version() {
|
|
local version_file="$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/VERSION"
|
|
local version="$(cat "$version_file" 2>/dev/null || echo 'unknown')"
|
|
echo "dokku-docker-compose $version"
|
|
}
|
|
|
|
# Run main function if this file is executed directly
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
main "$@"
|
|
fi
|