Rustelo/config/scripts/manage-config.sh

656 lines
16 KiB
Bash
Raw Normal View History

2025-07-07 23:13:01 +01:00
#!/bin/bash
# Configuration Management Script for Rustelo
# Provides commands to manage, validate, and deploy configurations
# Usage: ./manage-config.sh [command] [options]
set -e
# Script configuration
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CONFIG_DIR="$(dirname "$SCRIPT_DIR")"
PROJECT_ROOT="$(dirname "$CONFIG_DIR")"
BACKUP_DIR="$CONFIG_DIR/backups"
ENVIRONMENTS=("dev" "prod" "example")
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_debug() {
if [ "${DEBUG:-0}" = "1" ]; then
echo -e "${PURPLE}[DEBUG]${NC} $1"
fi
}
# Show help
show_help() {
cat << EOF
Configuration Management Script for Rustelo
USAGE:
$0 [COMMAND] [OPTIONS]
COMMANDS:
build ENV [OUTPUT] Build configuration for environment
validate ENV Validate configuration for environment
list-features List available features
list-environments List available environments
backup ENV Backup existing configuration
restore BACKUP_FILE Restore configuration from backup
diff ENV1 ENV2 Compare configurations between environments
template FEATURE Create new feature template
clean Clean generated configurations
status Show configuration status
help Show this help message
ENVIRONMENTS:
dev Development environment
prod Production environment
example Example/template environment
OPTIONS:
--debug Enable debug output
--dry-run Show what would be done without executing
--force Force operation without confirmation
--quiet Suppress non-error output
--backup-dir DIR Use custom backup directory
EXAMPLES:
$0 build dev # Build dev configuration
$0 build prod config.prod.toml # Build prod config with custom name
$0 validate dev # Validate dev configuration
$0 diff dev prod # Compare dev and prod configurations
$0 backup prod # Backup prod configuration
$0 template auth # Create new auth feature template
$0 clean # Clean all generated configs
$0 status # Show configuration status
ENVIRONMENT VARIABLES:
CONFIG_DEBUG=1 Enable debug output
CONFIG_QUIET=1 Suppress non-error output
CONFIG_FORCE=1 Force operations without confirmation
CONFIG_BACKUP_DIR=path Custom backup directory
EOF
}
# Parse command line arguments
parse_args() {
COMMAND=""
ENV=""
OUTPUT=""
DEBUG="${DEBUG:-0}"
DRY_RUN="${DRY_RUN:-0}"
FORCE="${FORCE:-0}"
QUIET="${QUIET:-0}"
BACKUP_DIR_OVERRIDE=""
while [[ $# -gt 0 ]]; do
case $1 in
--debug)
DEBUG=1
shift
;;
--dry-run)
DRY_RUN=1
shift
;;
--force)
FORCE=1
shift
;;
--quiet)
QUIET=1
shift
;;
--backup-dir)
BACKUP_DIR_OVERRIDE="$2"
shift 2
;;
build|validate|backup|restore|diff|template|clean|status|list-features|list-environments|help)
COMMAND="$1"
shift
;;
*)
if [ -z "$ENV" ]; then
ENV="$1"
elif [ -z "$OUTPUT" ]; then
OUTPUT="$1"
else
log_error "Unknown argument: $1"
exit 1
fi
shift
;;
esac
done
# Override backup directory if specified
if [ -n "$BACKUP_DIR_OVERRIDE" ]; then
BACKUP_DIR="$BACKUP_DIR_OVERRIDE"
fi
# Apply environment variables
[ "${CONFIG_DEBUG:-0}" = "1" ] && DEBUG=1
[ "${CONFIG_QUIET:-0}" = "1" ] && QUIET=1
[ "${CONFIG_FORCE:-0}" = "1" ] && FORCE=1
[ -n "${CONFIG_BACKUP_DIR:-}" ] && BACKUP_DIR="$CONFIG_BACKUP_DIR"
}
# Check if environment is valid
validate_environment() {
local env="$1"
for valid_env in "${ENVIRONMENTS[@]}"; do
if [ "$env" = "$valid_env" ]; then
return 0
fi
done
log_error "Invalid environment: $env"
log_error "Valid environments: ${ENVIRONMENTS[*]}"
return 1
}
# Create backup directory if it doesn't exist
ensure_backup_dir() {
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR"
log_debug "Created backup directory: $BACKUP_DIR"
fi
}
# Build configuration
cmd_build() {
local env="$1"
local output="${2:-config.toml}"
if [ -z "$env" ]; then
log_error "Environment required for build command"
return 1
fi
if ! validate_environment "$env"; then
return 1
fi
log_info "Building configuration for environment: $env"
# Use Python script if available, otherwise use bash script
if [ "$DRY_RUN" = "1" ]; then
log_info "Would build configuration using shell script"
return 0
fi
"$SCRIPT_DIR/build-config.sh" "$env" "$output"
}
# Validate configuration
cmd_validate() {
local env="$1"
if [ -z "$env" ]; then
log_error "Environment required for validate command"
return 1
fi
if ! validate_environment "$env"; then
return 1
fi
log_info "Validating configuration for environment: $env"
if [ "$DRY_RUN" = "1" ]; then
log_info "Would validate configuration"
return 0
fi
# Use Python script if available
CONFIG_VALIDATE_ONLY=1 "$SCRIPT_DIR/build-config.sh" "$env"
}
# List available features
cmd_list_features() {
log_info "Available features:"
if [ -d "$CONFIG_DIR/features" ]; then
for feature_dir in "$CONFIG_DIR/features"/*; do
if [ -d "$feature_dir" ]; then
local feature_name=$(basename "$feature_dir")
log_info " - $feature_name"
# Show available environments for this feature
local envs=()
for env in "${ENVIRONMENTS[@]}"; do
if [ -f "$feature_dir/$env.toml" ]; then
envs+=("$env")
fi
done
if [ ${#envs[@]} -gt 0 ]; then
log_info " Environments: ${envs[*]}"
fi
fi
done
else
log_error "Features directory not found: $CONFIG_DIR/features"
return 1
fi
}
# List available environments
cmd_list_environments() {
log_info "Available environments:"
for env in "${ENVIRONMENTS[@]}"; do
log_info " - $env"
# Check if base configuration exists
if [ -f "$CONFIG_DIR/base/$env.toml" ]; then
log_info " Base config: ✓"
else
log_info " Base config: ✗"
fi
# Count available features
local feature_count=0
if [ -d "$CONFIG_DIR/features" ]; then
for feature_dir in "$CONFIG_DIR/features"/*; do
if [ -d "$feature_dir" ] && [ -f "$feature_dir/$env.toml" ]; then
((feature_count++))
fi
done
fi
log_info " Available features: $feature_count"
done
}
# Compare configurations between environments
cmd_diff() {
local env1="$1"
local env2="$2"
if [ -z "$env1" ] || [ -z "$env2" ]; then
log_error "Two environments required for diff command"
return 1
fi
if ! validate_environment "$env1" || ! validate_environment "$env2"; then
return 1
fi
log_info "Comparing configurations: $env1 vs $env2"
# Create temporary files
local temp1=$(mktemp)
local temp2=$(mktemp)
trap "rm -f $temp1 $temp2" EXIT
# Build configurations
if ! cmd_build "$env1" "$temp1"; then
log_error "Failed to build configuration for $env1"
return 1
fi
if ! cmd_build "$env2" "$temp2"; then
log_error "Failed to build configuration for $env2"
return 1
fi
# Compare configurations
if command -v diff &> /dev/null; then
diff -u "$temp1" "$temp2" || true
else
log_warning "diff command not available, using basic comparison"
if cmp -s "$temp1" "$temp2"; then
log_info "Configurations are identical"
else
log_info "Configurations differ"
fi
fi
}
# Create backup of configuration
cmd_backup() {
local env="$1"
local config_file="${2:-config.toml}"
if [ -z "$env" ]; then
log_error "Environment required for backup command"
return 1
fi
if ! validate_environment "$env"; then
return 1
fi
ensure_backup_dir
local timestamp=$(date +%Y%m%d_%H%M%S)
local backup_file="$BACKUP_DIR/config_${env}_${timestamp}.toml"
if [ -f "$config_file" ]; then
if [ "$DRY_RUN" = "1" ]; then
log_info "Would backup $config_file to $backup_file"
return 0
fi
cp "$config_file" "$backup_file"
log_success "Configuration backed up to: $backup_file"
else
log_error "Configuration file not found: $config_file"
return 1
fi
}
# Restore configuration from backup
cmd_restore() {
local backup_file="$1"
local output_file="${2:-config.toml}"
if [ -z "$backup_file" ]; then
log_error "Backup file required for restore command"
return 1
fi
if [ ! -f "$backup_file" ]; then
log_error "Backup file not found: $backup_file"
return 1
fi
if [ "$DRY_RUN" = "1" ]; then
log_info "Would restore $backup_file to $output_file"
return 0
fi
# Create backup of current file if it exists
if [ -f "$output_file" ]; then
local timestamp=$(date +%Y%m%d_%H%M%S)
local current_backup="$BACKUP_DIR/config_current_${timestamp}.toml"
ensure_backup_dir
cp "$output_file" "$current_backup"
log_info "Current configuration backed up to: $current_backup"
fi
cp "$backup_file" "$output_file"
log_success "Configuration restored from: $backup_file"
}
# Create new feature template
cmd_template() {
local feature_name="$1"
if [ -z "$feature_name" ]; then
log_error "Feature name required for template command"
return 1
fi
local feature_dir="$CONFIG_DIR/features/$feature_name"
if [ -d "$feature_dir" ]; then
if [ "$FORCE" != "1" ]; then
log_error "Feature directory already exists: $feature_dir"
log_error "Use --force to overwrite"
return 1
fi
fi
if [ "$DRY_RUN" = "1" ]; then
log_info "Would create feature template: $feature_name"
return 0
fi
# Create feature directory
mkdir -p "$feature_dir"
# Create template files for each environment
for env in "${ENVIRONMENTS[@]}"; do
local template_file="$feature_dir/$env.toml"
cat > "$template_file" << EOF
# $feature_name Feature Configuration - $(echo $env | sed 's/./\U&/') Environment
# Settings for the $feature_name feature
[features]
$feature_name = true
[$feature_name]
enabled = true
# Add your feature-specific settings here
# Example configuration options:
# option1 = "value1"
# option2 = 42
# option3 = true
EOF
log_info "Created template file: $template_file"
done
# Create README for the feature
cat > "$feature_dir/README.md" << EOF
# $feature_name Feature
Description of the $feature_name feature.
## Configuration Options
### Environment-Specific Settings
#### Development (\`dev.toml\`)
- Optimized for development and debugging
- Relaxed security settings
- Verbose logging enabled
#### Production (\`prod.toml\`)
- Optimized for production performance
- Strict security settings
- Minimal logging
#### Example (\`example.toml\`)
- Complete documentation of all options
- Best practice configurations
- Commented examples
## Usage
Enable this feature by setting:
\`\`\`toml
[features]
$feature_name = true
\`\`\`
## Dependencies
List any features that this feature depends on.
## Security Considerations
Document any security implications of this feature.
EOF
log_success "Feature template created: $feature_name"
}
# Clean generated configurations
cmd_clean() {
log_info "Cleaning generated configurations..."
if [ "$DRY_RUN" = "1" ]; then
log_info "Would clean generated configuration files"
return 0
fi
local cleaned_count=0
# Remove generated config files
for config_file in config.toml config.*.toml; do
if [ -f "$config_file" ]; then
rm "$config_file"
log_info "Removed: $config_file"
((cleaned_count++))
fi
done
# Remove temporary files
for temp_file in /tmp/config_*.toml /tmp/rustelo_config_*.toml; do
if [ -f "$temp_file" ]; then
rm "$temp_file"
log_info "Removed: $temp_file"
((cleaned_count++))
fi
done
log_success "Cleaned $cleaned_count files"
}
# Show configuration status
cmd_status() {
log_info "Configuration system status:"
# Check directories
log_info "Directories:"
for dir in base features scripts; do
if [ -d "$CONFIG_DIR/$dir" ]; then
log_info " $dir: ✓"
else
log_info " $dir: ✗"
fi
done
# Check base configurations
log_info "Base configurations:"
for env in "${ENVIRONMENTS[@]}"; do
if [ -f "$CONFIG_DIR/base/$env.toml" ]; then
log_info " $env: ✓"
else
log_info " $env: ✗"
fi
done
# Check features
log_info "Features:"
if [ -d "$CONFIG_DIR/features" ]; then
for feature_dir in "$CONFIG_DIR/features"/*; do
if [ -d "$feature_dir" ]; then
local feature_name=$(basename "$feature_dir")
local env_count=0
for env in "${ENVIRONMENTS[@]}"; do
if [ -f "$feature_dir/$env.toml" ]; then
((env_count++))
fi
done
log_info " $feature_name: $env_count/${#ENVIRONMENTS[@]} environments"
fi
done
fi
# Check scripts
log_info "Scripts:"
for script in build-config.sh; do
if [ -f "$SCRIPT_DIR/$script" ]; then
log_info " $script: ✓"
else
log_error " $script: ✗"
fi
done
# Check tools
log_info "Tools:"
if command -v python3 &> /dev/null; then
log_info " python3: ✓"
if python3 -c "import toml" 2>/dev/null; then
log_info " toml (Python): ✓"
else
log_info " toml (Python): ✗"
fi
else
log_info " python3: ✗"
fi
if command -v toml &> /dev/null; then
log_info " toml (CLI): ✓"
else
log_info " toml (CLI): ✗"
fi
}
# Main function
main() {
parse_args "$@"
# Enable debug if requested
if [ "$DEBUG" = "1" ]; then
set -x
fi
# Handle quiet mode
if [ "$QUIET" = "1" ]; then
exec 1>/dev/null
fi
# Execute command
case "$COMMAND" in
build)
cmd_build "$ENV" "$OUTPUT"
;;
validate)
cmd_validate "$ENV"
;;
list-features)
cmd_list_features
;;
list-environments)
cmd_list_environments
;;
diff)
cmd_diff "$ENV" "$OUTPUT"
;;
backup)
cmd_backup "$ENV" "$OUTPUT"
;;
restore)
cmd_restore "$ENV" "$OUTPUT"
;;
template)
cmd_template "$ENV"
;;
clean)
cmd_clean
;;
status)
cmd_status
;;
help|"")
show_help
;;
*)
log_error "Unknown command: $COMMAND"
show_help
exit 1
;;
esac
}
# Run main function
main "$@"