#!/bin/bash # Kubernetes Dependency Checking # File: dependency-checks.sh # Check if a service is ready check_service_ready() { local service=$1 local namespace=${2:-$K8S_NAMESPACE} local timeout=${3:-60} log_operation "INFO" "Checking if service '$service' is ready in namespace '$namespace'" # Check if deployment exists if ! kubectl get deployment "$service" -n "$namespace" &>/dev/null; then log_dependency_check "$service" "NOT_FOUND" "Deployment does not exist" return 1 fi # Check if deployment is ready local ready_replicas ready_replicas=$(kubectl get deployment "$service" -n "$namespace" -o jsonpath='{.status.readyReplicas}' 2>/dev/null) local desired_replicas desired_replicas=$(kubectl get deployment "$service" -n "$namespace" -o jsonpath='{.spec.replicas}' 2>/dev/null) if [[ -z "$ready_replicas" ]]; then ready_replicas=0 fi if [[ -z "$desired_replicas" ]]; then desired_replicas=1 fi if [[ "$ready_replicas" -eq "$desired_replicas" && "$ready_replicas" -gt 0 ]]; then log_dependency_check "$service" "READY" "All $ready_replicas/$desired_replicas replicas are ready" return 0 else log_dependency_check "$service" "NOT_READY" "Only $ready_replicas/$desired_replicas replicas are ready" return 1 fi } # Wait for a service to become ready wait_for_service_ready() { local service=$1 local namespace=${2:-$K8S_NAMESPACE} local timeout=${3:-300} local check_interval=${4:-10} log_operation "INFO" "Waiting for service '$service' to become ready (timeout: ${timeout}s)" local elapsed=0 while [[ $elapsed -lt $timeout ]]; do if check_service_ready "$service" "$namespace" 0; then log_operation "SUCCESS" "Service '$service' is ready after ${elapsed}s" return 0 fi log_operation "DEBUG" "Service '$service' not ready yet, waiting ${check_interval}s... (${elapsed}/${timeout}s)" sleep "$check_interval" elapsed=$((elapsed + check_interval)) done log_operation "ERROR" "Service '$service' failed to become ready within ${timeout}s" return 1 } # Check if infrastructure services are ready check_infrastructure_ready() { log_operation "INFO" "Checking infrastructure readiness" local infrastructure_services infrastructure_services=$(get_services_in_group "infrastructure") if [[ $? -ne 0 ]]; then log_operation "ERROR" "Failed to get infrastructure services" return 1 fi local all_ready=true for service in $infrastructure_services; do if ! check_service_ready "$service" "$K8S_NAMESPACE" 0; then all_ready=false log_operation "WARNING" "Infrastructure service '$service' is not ready" fi done if [[ "$all_ready" == "true" ]]; then log_operation "SUCCESS" "All infrastructure services are ready" return 0 else log_operation "ERROR" "Some infrastructure services are not ready" log_operation "INFO" "You may need to start infrastructure first: kup infrastructure" return 1 fi } # Check app-specific dependencies check_app_dependencies() { local service=$1 log_operation "INFO" "Checking dependencies for service '$service'" case "$service" in "eveai-workers"|"eveai-chat-workers") # Workers need API to be running if ! check_service_ready "eveai-api" "$K8S_NAMESPACE" 0; then log_operation "ERROR" "Service '$service' requires eveai-api to be running" log_operation "INFO" "Start API first: kup-api" return 1 fi ;; "eveai-beat") # Beat needs Redis to be running if ! check_service_ready "redis" "$K8S_NAMESPACE" 0; then log_operation "ERROR" "Service '$service' requires redis to be running" log_operation "INFO" "Start infrastructure first: kup infrastructure" return 1 fi ;; "eveai-app"|"eveai-api"|"eveai-chat-client"|"eveai-entitlements") # Core apps need infrastructure if ! check_infrastructure_ready; then log_operation "ERROR" "Service '$service' requires infrastructure to be running" return 1 fi ;; *) log_operation "DEBUG" "No specific dependencies defined for service '$service'" ;; esac log_operation "SUCCESS" "All dependencies satisfied for service '$service'" return 0 } # Check if a pod is running and ready check_pod_ready() { local pod_selector=$1 local namespace=${2:-$K8S_NAMESPACE} local pods pods=$(kubectl get pods -l "$pod_selector" -n "$namespace" --no-headers 2>/dev/null) if [[ -z "$pods" ]]; then return 1 fi # Check if any pod is in Running state and Ready while IFS= read -r line; do local status=$(echo "$line" | awk '{print $3}') local ready=$(echo "$line" | awk '{print $2}') if [[ "$status" == "Running" && "$ready" =~ ^[1-9]/[1-9] ]]; then # Extract ready count and total count local ready_count=$(echo "$ready" | cut -d'/' -f1) local total_count=$(echo "$ready" | cut -d'/' -f2) if [[ "$ready_count" -eq "$total_count" ]]; then return 0 fi fi done <<< "$pods" return 1 } # Check service health endpoint check_service_health() { local service=$1 local namespace=${2:-$K8S_NAMESPACE} local health_endpoint health_endpoint=$(get_service_health_endpoint "$service") if [[ -z "$health_endpoint" ]]; then log_operation "DEBUG" "No health endpoint defined for service '$service'" return 0 fi case "$service" in "redis") # Check Redis with ping if kubectl exec -n "$namespace" deployment/redis -- redis-cli ping &>/dev/null; then log_operation "SUCCESS" "Redis health check passed" return 0 else log_operation "WARNING" "Redis health check failed" return 1 fi ;; "minio") # Check MinIO readiness if kubectl exec -n "$namespace" deployment/minio -- mc ready local &>/dev/null; then log_operation "SUCCESS" "MinIO health check passed" return 0 else log_operation "WARNING" "MinIO health check failed" return 1 fi ;; *) # For other services, try HTTP health check if [[ "$health_endpoint" =~ ^/.*:[0-9]+$ ]]; then local path=$(echo "$health_endpoint" | cut -d':' -f1) local port=$(echo "$health_endpoint" | cut -d':' -f2) # Use port-forward to check health endpoint local pod pod=$(kubectl get pods -l "app=$service" -n "$namespace" --no-headers -o custom-columns=":metadata.name" | head -n1) if [[ -n "$pod" ]]; then if timeout 10 kubectl exec -n "$namespace" "$pod" -- curl -f -s "http://localhost:$port$path" &>/dev/null; then log_operation "SUCCESS" "Health check passed for service '$service'" return 0 else log_operation "WARNING" "Health check failed for service '$service'" return 1 fi fi fi ;; esac log_operation "DEBUG" "Could not perform health check for service '$service'" return 0 } # Comprehensive dependency check for a service group check_group_dependencies() { local group=$1 log_operation "INFO" "Checking dependencies for service group '$group'" local services services=$(get_services_in_group "$group") if [[ $? -ne 0 ]]; then return 1 fi # Sort services by deployment order local sorted_services read -ra service_array <<< "$services" sorted_services=$(sort_services_by_deploy_order "${service_array[@]}") local all_dependencies_met=true for service in $sorted_services; do local dependencies dependencies=$(get_service_dependencies "$service") for dep in $dependencies; do if ! check_service_ready "$dep" "$K8S_NAMESPACE" 0; then log_operation "ERROR" "Dependency '$dep' not ready for service '$service'" all_dependencies_met=false fi done # Check app-specific dependencies if ! check_app_dependencies "$service"; then all_dependencies_met=false fi done if [[ "$all_dependencies_met" == "true" ]]; then log_operation "SUCCESS" "All dependencies satisfied for group '$group'" return 0 else log_operation "ERROR" "Some dependencies not satisfied for group '$group'" return 1 fi } # Show dependency status for all services show_dependency_status() { echo "🔍 Dependency Status Overview:" echo "==============================" local all_services all_services=$(get_services_in_group "all") for service in $all_services; do local status="❌ NOT READY" local health_status="" if check_service_ready "$service" "$K8S_NAMESPACE" 0; then status="✅ READY" # Check health if available if check_service_health "$service" "$K8S_NAMESPACE"; then health_status=" (healthy)" else health_status=" (unhealthy)" fi fi echo " $service: $status$health_status" done } # Export functions for use in other scripts if [[ -n "$ZSH_VERSION" ]]; then typeset -f check_service_ready wait_for_service_ready check_infrastructure_ready > /dev/null typeset -f check_app_dependencies check_pod_ready check_service_health > /dev/null typeset -f check_group_dependencies show_dependency_status > /dev/null else export -f check_service_ready wait_for_service_ready check_infrastructure_ready export -f check_app_dependencies check_pod_ready check_service_health export -f check_group_dependencies show_dependency_status fi