@@ -302,8 +302,187 @@ validate_helm_chart() {
302302 return 0
303303}
304304
305+ # Validate K3s cluster readiness (extracted from CI workflow)
306+ validate_k3s_readiness () {
307+ log_info " === Waiting for K3s cluster to be ready ==="
308+
309+ # Verify kubectl works
310+ if ! kubectl cluster-info > /dev/null 2>&1 ; then
311+ log_error " Cannot connect to K3s cluster"
312+ return 1
313+ fi
314+
315+ if ! kubectl get nodes > /dev/null 2>&1 ; then
316+ log_error " Cannot get cluster nodes"
317+ return 1
318+ fi
319+
320+ # Wait for core components
321+ log_info " Waiting for core DNS..."
322+ if ! kubectl wait --for=condition=Ready pod -l k8s-app=kube-dns -n kube-system --timeout=300s 2> /dev/null; then
323+ log_error " Core DNS not ready"
324+ return 1
325+ fi
326+
327+ log_info " Waiting for Traefik..."
328+ if ! kubectl wait --for=condition=Ready pod -l app.kubernetes.io/name=traefik -n kube-system --timeout=300s 2> /dev/null; then
329+ log_error " Traefik not ready"
330+ return 1
331+ fi
332+
333+ # Verify Traefik CRDs
334+ log_info " Verifying Traefik CRDs..."
335+ local timeout=300
336+ local counter=0
337+ for crd in " middlewares.traefik.io" " ingressroutes.traefik.io" ; do
338+ while [ $counter -lt $timeout ] && ! kubectl get crd " $crd " & > /dev/null; do
339+ sleep 3
340+ counter=$(( counter + 3 ))
341+ done
342+ if [ $counter -ge $timeout ]; then
343+ log_error " Timeout waiting for CRD: $crd "
344+ return 1
345+ fi
346+ done
347+
348+ log_info " ✅ K3s cluster ready"
349+ return 0
350+ }
351+
352+ # Wait for eoAPI deployments to be available
353+ validate_deployments_ready () {
354+ local namespace=" $1 "
355+ local release_name=" $2 "
356+ local timeout=" ${3:- 300s} "
357+
358+ log_info " === Waiting for deployments to be ready ==="
359+
360+ # Verify namespace exists
361+ if ! kubectl get namespace " $namespace " > /dev/null 2>&1 ; then
362+ log_error " Namespace $namespace does not exist"
363+ return 1
364+ fi
365+
366+ # Wait for core deployments
367+ local deployments=(" ${release_name} -stac" " ${release_name} -raster" " ${release_name} -vector" )
368+ local failed=false
369+
370+ for deployment in " ${deployments[@]} " ; do
371+ log_info " Waiting for deployment: $deployment "
372+ if ! kubectl wait --for=condition=available " deployment/$deployment " -n " $namespace " --timeout=" $timeout " 2> /dev/null; then
373+ log_error " Deployment $deployment not ready"
374+ failed=true
375+ fi
376+ done
377+
378+ if [ " $failed " = true ]; then
379+ return 1
380+ fi
381+
382+ log_info " ✅ All deployments ready"
383+ return 0
384+ }
385+
386+ # Validate API connectivity through ingress
387+ validate_api_connectivity () {
388+ local ingress_host=" ${1:- eoapi.local} "
389+ local max_attempts=" ${2:- 30} "
390+
391+ log_info " === Testing API connectivity through ingress ==="
392+
393+ # Add ingress host to /etc/hosts if needed and not already present
394+ if [[ " $ingress_host " == * .local ]] && ! grep -q " $ingress_host " /etc/hosts 2> /dev/null; then
395+ local node_ip
396+ node_ip=$( kubectl get nodes -o jsonpath=' {.items[0].status.addresses[?(@.type=="InternalIP")].address}' 2> /dev/null)
397+ if [ -n " $node_ip " ]; then
398+ log_info " Adding $ingress_host to /etc/hosts with IP $node_ip "
399+ echo " $node_ip $ingress_host " | sudo tee -a /etc/hosts > /dev/null
400+ fi
401+ fi
402+
403+ # Test STAC API
404+ log_info " Testing STAC API..."
405+ local i
406+ for i in $( seq 1 " $max_attempts " ) ; do
407+ if curl -s " http://${ingress_host} /stac/_mgmt/ping" > /dev/null 2>&1 ; then
408+ log_info " ✅ STAC API accessible through ingress"
409+ break
410+ fi
411+ log_debug " Waiting for STAC API... (attempt $i /$max_attempts )"
412+ sleep 3
413+ done
414+ if [ " $i " -eq " $max_attempts " ]; then
415+ log_error " STAC API not accessible after $max_attempts attempts"
416+ return 1
417+ fi
418+
419+ # Test Raster API
420+ log_info " Testing Raster API..."
421+ for i in $( seq 1 " $max_attempts " ) ; do
422+ if curl -s " http://${ingress_host} /raster/healthz" > /dev/null 2>&1 ; then
423+ log_info " ✅ Raster API accessible through ingress"
424+ break
425+ fi
426+ log_debug " Waiting for Raster API... (attempt $i /$max_attempts )"
427+ sleep 3
428+ done
429+ if [ " $i " -eq " $max_attempts " ]; then
430+ log_error " Raster API not accessible after $max_attempts attempts"
431+ return 1
432+ fi
433+
434+ # Test Vector API
435+ log_info " Testing Vector API..."
436+ for i in $( seq 1 " $max_attempts " ) ; do
437+ if curl -s " http://${ingress_host} /vector/healthz" > /dev/null 2>&1 ; then
438+ log_info " ✅ Vector API accessible through ingress"
439+ break
440+ fi
441+ log_debug " Waiting for Vector API... (attempt $i /$max_attempts )"
442+ sleep 3
443+ done
444+ if [ " $i " -eq " $max_attempts " ]; then
445+ log_error " Vector API not accessible after $max_attempts attempts"
446+ return 1
447+ fi
448+
449+ log_info " ✅ All APIs accessible through ingress"
450+ return 0
451+ }
452+
453+ # Wait for ingress to be ready
454+ validate_ingress_ready () {
455+ local namespace=" $1 "
456+ local ingress_name=" ${2:- } "
457+ local timeout=" ${3:- 60s} "
458+
459+ log_info " Waiting for ingress to be ready..."
460+
461+ # Get ingress resources
462+ if ! kubectl get ingress -n " $namespace " > /dev/null 2>&1 ; then
463+ log_warn " No ingress resources found in namespace $namespace "
464+ return 0
465+ fi
466+
467+ # If specific ingress name provided, wait for it
468+ if [ -n " $ingress_name " ]; then
469+ if kubectl get ingress " $ingress_name " -n " $namespace " > /dev/null 2>&1 ; then
470+ log_debug " Ingress $ingress_name exists in namespace $namespace "
471+ else
472+ log_warn " Ingress $ingress_name not found in namespace $namespace "
473+ fi
474+ fi
475+
476+ # Wait for Traefik to pick up ingress rules
477+ sleep 10
478+
479+ log_info " ✅ Ingress ready"
480+ return 0
481+ }
482+
305483# Export validation functions
306484export -f validate_kubectl validate_helm validate_python3 validate_jq
307485export -f validate_deploy_tools validate_test_tools validate_local_cluster_tools
308486export -f validate_cluster_connection validate_cluster_permissions
309487export -f validate_file_readable validate_json_file validate_yaml_file validate_helm_chart
488+ export -f validate_k3s_readiness validate_deployments_ready validate_api_connectivity validate_ingress_ready
0 commit comments