Files
Sankofa/scripts/validate-and-optimize-vms.sh

214 lines
6.1 KiB
Bash
Raw Permalink Normal View History

#!/bin/bash
# Validate and optimize VM YAML configurations
# Ensures quota checks, non-compounded commands, and best practices
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
VM_DIR="${PROJECT_ROOT}/examples/production"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
log() {
echo -e "${BLUE}[$(date +'%H:%M:%S')]${NC} $*"
}
log_success() {
echo -e "${GREEN}[$(date +'%H:%M:%S')] ✅${NC} $*"
}
log_warning() {
echo -e "${YELLOW}[$(date +'%H:%M:%S')] ⚠️${NC} $*"
}
log_error() {
echo -e "${RED}[$(date +'%H:%M:%S')] ❌${NC} $*"
}
# Check if YAML file has required fields
check_yaml_structure() {
local file=$1
local errors=0
# Check for required fields
if ! grep -q "kind: ProxmoxVM" "$file"; then
log_error "$file: Missing 'kind: ProxmoxVM'"
errors=$((errors + 1))
fi
if ! grep -q "tenant.sankofa.nexus/id" "$file"; then
log_warning "$file: Missing tenant label (may be intentional for infrastructure VMs)"
fi
if ! grep -q "image:" "$file"; then
log_error "$file: Missing image specification"
errors=$((errors + 1))
fi
# Check image format
if grep -q "image:" "$file"; then
local image=$(grep "image:" "$file" | head -1 | sed 's/.*image: *"\(.*\)".*/\1/')
if [[ -z "$image" ]]; then
log_error "$file: Image specification is empty"
errors=$((errors + 1))
fi
fi
return $errors
}
# Check for compounded commands (should be avoided)
check_compounded_commands() {
local file=$1
local warnings=0
# Check for problematic patterns
if grep -q "systemctl.*&&\|systemctl.*||" "$file"; then
log_warning "$file: Found compounded systemctl commands (should be separate)"
warnings=$((warnings + 1))
fi
# Check for command chains in runcmd
if grep -A 5 "runcmd:" "$file" | grep -q ".*&&.*"; then
log_warning "$file: Found command chains with && in runcmd (should be separate list items)"
warnings=$((warnings + 1))
fi
# Note: || true is acceptable for non-critical error handling
# But we should document this
return $warnings
}
# Check for quota check annotations
check_quota_annotations() {
local file=$1
local warnings=0
# Check if tenant label exists
if grep -q "tenant.sankofa.nexus/id" "$file"; then
local tenant=$(grep "tenant.sankofa.nexus/id" "$file" | sed 's/.*tenant.sankofa.nexus\/id: *"\(.*\)".*/\1/')
if [[ -n "$tenant" && "$tenant" != "infrastructure" ]]; then
# For tenant VMs, quota should be checked by controller
# But we can add annotation for explicit quota check
if ! grep -q "phoenix.sankofa.nexus/quota-check" "$file"; then
log_warning "$file: Tenant VM should have quota-check annotation (controller will check automatically)"
fi
fi
fi
return $warnings
}
# Validate image specification
check_image_spec() {
local file=$1
local errors=0
if grep -q "image:" "$file"; then
local image=$(grep "image:" "$file" | head -1 | sed 's/.*image: *"\(.*\)".*/\1/')
# Check for valid image format
if [[ ! "$image" =~ ^[a-zA-Z0-9._-]+$ ]]; then
log_error "$file: Invalid image format: $image"
errors=$((errors + 1))
fi
# Check for recommended image
if [[ "$image" != "ubuntu-22.04-cloud" ]]; then
log_warning "$file: Using non-standard image: $image (recommended: ubuntu-22.04-cloud)"
fi
fi
return $errors
}
# Check for best practices
check_best_practices() {
local file=$1
local warnings=0
# Check for QEMU guest agent
if ! grep -q "qemu-guest-agent" "$file"; then
log_warning "$file: Missing qemu-guest-agent package"
warnings=$((warnings + 1))
fi
# Check for guest agent enable/start
if ! grep -q "systemctl enable qemu-guest-agent" "$file"; then
log_warning "$file: Missing 'systemctl enable qemu-guest-agent'"
warnings=$((warnings + 1))
fi
if ! grep -q "systemctl start qemu-guest-agent" "$file"; then
log_warning "$file: Missing 'systemctl start qemu-guest-agent'"
warnings=$((warnings + 1))
fi
# Check for package verification
if ! grep -q "Verifying required packages" "$file"; then
log_warning "$file: Missing package verification step"
warnings=$((warnings + 1))
fi
return $warnings
}
# Main validation
main() {
log "Validating and optimizing VM YAML configurations..."
echo
local total_files=0
local total_errors=0
local total_warnings=0
# Find all YAML files
while IFS= read -r -d '' file; do
total_files=$((total_files + 1))
log "Checking: $file"
local file_errors=0
local file_warnings=0
check_yaml_structure "$file" || file_errors=$?
check_compounded_commands "$file" || file_warnings=$?
check_quota_annotations "$file" || file_warnings=$((file_warnings + $?))
check_image_spec "$file" || file_errors=$((file_errors + $?))
check_best_practices "$file" || file_warnings=$((file_warnings + $?))
total_errors=$((total_errors + file_errors))
total_warnings=$((total_warnings + file_warnings))
if [[ $file_errors -eq 0 && $file_warnings -eq 0 ]]; then
log_success "$file: All checks passed"
fi
echo
done < <(find "$VM_DIR" -name "*.yaml" -type f -print0)
# Summary
echo
log "=== Validation Summary ==="
echo "Files checked: $total_files"
echo "Errors: $total_errors"
echo "Warnings: $total_warnings"
echo
if [[ $total_errors -eq 0 ]]; then
log_success "All VM configurations are valid!"
return 0
else
log_error "Found $total_errors errors. Please fix before deployment."
return 1
fi
}
main "$@"