- Complete project structure with Next.js frontend - GraphQL API backend with Apollo Server - Portal application with NextAuth - Crossplane Proxmox provider - GitOps configurations - CI/CD pipelines - Testing infrastructure (Vitest, Jest, Go tests) - Error handling and monitoring - Security hardening - UI component library - Documentation
200 lines
5.2 KiB
Bash
Executable File
200 lines
5.2 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# Post-Install Validation Script
|
|
|
|
ERRORS=0
|
|
WARNINGS=0
|
|
|
|
log() {
|
|
echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" >&2
|
|
}
|
|
|
|
error() {
|
|
log "ERROR: $*"
|
|
((ERRORS++))
|
|
}
|
|
|
|
warning() {
|
|
log "WARNING: $*"
|
|
((WARNINGS++))
|
|
}
|
|
|
|
success() {
|
|
log "✓ $*"
|
|
}
|
|
|
|
check_kubectl() {
|
|
log "Checking kubectl connectivity..."
|
|
|
|
if ! kubectl cluster-info &> /dev/null; then
|
|
error "Cannot connect to Kubernetes cluster"
|
|
return 1
|
|
fi
|
|
|
|
success "Kubernetes cluster is accessible"
|
|
return 0
|
|
}
|
|
|
|
check_namespaces() {
|
|
log "Checking required namespaces..."
|
|
|
|
local namespaces=(
|
|
"argocd"
|
|
"rancher-system"
|
|
"crossplane-system"
|
|
"vault"
|
|
"monitoring"
|
|
"portal"
|
|
"keycloak"
|
|
)
|
|
|
|
for ns in "${namespaces[@]}"; do
|
|
if kubectl get namespace "${ns}" &> /dev/null; then
|
|
success "Namespace ${ns} exists"
|
|
else
|
|
error "Namespace ${ns} does not exist"
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_deployments() {
|
|
log "Checking deployments..."
|
|
|
|
local deployments=(
|
|
"argocd/argocd-server"
|
|
"rancher-system/rancher"
|
|
"crossplane-system/crossplane"
|
|
"vault/vault"
|
|
"monitoring/kube-prometheus-stack"
|
|
"portal/portal"
|
|
)
|
|
|
|
for deployment in "${deployments[@]}"; do
|
|
IFS='/' read -r namespace name <<< "${deployment}"
|
|
if kubectl get deployment "${name}" -n "${namespace}" &> /dev/null; then
|
|
READY=$(kubectl get deployment "${name}" -n "${namespace}" -o jsonpath='{.status.readyReplicas}')
|
|
DESIRED=$(kubectl get deployment "${name}" -n "${namespace}" -o jsonpath='{.status.replicas}')
|
|
if [ "${READY}" = "${DESIRED}" ] && [ "${READY}" != "0" ]; then
|
|
success "Deployment ${name} in ${namespace} is ready (${READY}/${DESIRED})"
|
|
else
|
|
warning "Deployment ${name} in ${namespace} is not ready (${READY}/${DESIRED})"
|
|
fi
|
|
else
|
|
error "Deployment ${name} in ${namespace} does not exist"
|
|
fi
|
|
done
|
|
}
|
|
|
|
check_argocd() {
|
|
log "Checking ArgoCD..."
|
|
|
|
if kubectl get deployment argocd-server -n argocd &> /dev/null; then
|
|
# Check if ArgoCD is accessible
|
|
if kubectl port-forward -n argocd svc/argocd-server 8080:443 &> /dev/null &
|
|
then
|
|
sleep 2
|
|
if curl -k -s https://localhost:8080 &> /dev/null; then
|
|
success "ArgoCD server is accessible"
|
|
else
|
|
warning "ArgoCD server may not be fully ready"
|
|
fi
|
|
pkill -f "port-forward.*argocd-server" || true
|
|
fi
|
|
else
|
|
error "ArgoCD server not found"
|
|
fi
|
|
}
|
|
|
|
check_crossplane() {
|
|
log "Checking Crossplane..."
|
|
|
|
if kubectl get deployment crossplane -n crossplane-system &> /dev/null; then
|
|
# Check if provider is installed
|
|
if kubectl get providerconfig -n crossplane-system &> /dev/null; then
|
|
success "Crossplane provider configs found"
|
|
else
|
|
warning "No Crossplane provider configs found"
|
|
fi
|
|
else
|
|
error "Crossplane not found"
|
|
fi
|
|
}
|
|
|
|
check_proxmox_connectivity() {
|
|
log "Checking Proxmox connectivity (if configured)..."
|
|
|
|
# This would check if Proxmox sites are reachable via tunnels
|
|
# Implementation depends on your setup
|
|
warning "Proxmox connectivity check not implemented"
|
|
}
|
|
|
|
check_cloudflare_tunnels() {
|
|
log "Checking Cloudflare tunnels..."
|
|
|
|
# Check if cloudflared processes are running on nodes
|
|
# This is a simplified check
|
|
if command -v cloudflared &> /dev/null; then
|
|
if systemctl is-active --quiet cloudflared-tunnel 2>/dev/null; then
|
|
success "Cloudflare tunnel service is active"
|
|
else
|
|
warning "Cloudflare tunnel service may not be running"
|
|
fi
|
|
else
|
|
warning "cloudflared not found (may not be installed on this node)"
|
|
fi
|
|
}
|
|
|
|
check_storage() {
|
|
log "Checking storage classes..."
|
|
|
|
if kubectl get storageclass &> /dev/null; then
|
|
DEFAULT_SC=$(kubectl get storageclass -o jsonpath='{.items[?(@.metadata.annotations.storageclass\.kubernetes\.io/is-default-class=="true")].metadata.name}')
|
|
if [ -n "${DEFAULT_SC}" ]; then
|
|
success "Default storage class: ${DEFAULT_SC}"
|
|
else
|
|
warning "No default storage class found"
|
|
fi
|
|
else
|
|
error "Cannot list storage classes"
|
|
fi
|
|
}
|
|
|
|
print_summary() {
|
|
log ""
|
|
log "=== Validation Summary ==="
|
|
log "Errors: ${ERRORS}"
|
|
log "Warnings: ${WARNINGS}"
|
|
log ""
|
|
|
|
if [ "${ERRORS}" -eq 0 ]; then
|
|
log "✓ All critical checks passed!"
|
|
if [ "${WARNINGS}" -gt 0 ]; then
|
|
log "⚠ Some warnings were found, but installation appears functional"
|
|
fi
|
|
return 0
|
|
else
|
|
log "✗ Some errors were found. Please review and fix them."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
main() {
|
|
log "Starting post-install validation..."
|
|
log ""
|
|
|
|
check_kubectl
|
|
check_namespaces
|
|
check_deployments
|
|
check_argocd
|
|
check_crossplane
|
|
check_proxmox_connectivity
|
|
check_cloudflare_tunnels
|
|
check_storage
|
|
|
|
print_summary
|
|
}
|
|
|
|
main "$@"
|
|
|