diff --git a/docs/DEPLOYMENT_TROUBLESHOOTING.md b/docs/DEPLOYMENT_TROUBLESHOOTING.md new file mode 100644 index 00000000..7065d5c6 --- /dev/null +++ b/docs/DEPLOYMENT_TROUBLESHOOTING.md @@ -0,0 +1,300 @@ +# Deployment Troubleshooting Guide + +This guide covers common issues you might encounter when deploying StreamSpace and their solutions. + +## Table of Contents + +- [Helm Chart Validation Issues](#helm-chart-validation-issues) +- [Image Pull Issues](#image-pull-issues) +- [Database Connection Issues](#database-connection-issues) +- [CRD Installation Issues](#crd-installation-issues) + +--- + +## Helm Chart Validation Issues + +### Issue: "Chart.yaml file is missing" error during helm lint + +**Symptoms:** +```bash +==> Linting /path/to/streamspace/chart +[ERROR] templates/: Chart.yaml file is missing +[ERROR] : unable to load chart + Chart.yaml file is missing + +Error: 1 chart(s) linted, 1 chart(s) failed +``` + +**Affected Versions:** +- Helm v3.19.0 (confirmed critical bug) +- Possibly affects v3.19.1+ as well +- Observed on macOS and Linux + +**Root Cause:** +Helm v3.19.0 has a **critical regression** in the chart loader (`helm.sh/helm/v3/pkg/chart/loader`) that **completely breaks chart loading**. The bug affects: +- ✗ `helm lint` - reports "Chart.yaml is missing" +- ✗ `helm template` - fails to load chart +- ✗ `helm install` from directory - fails with "Chart.yaml file is missing" +- ✗ `helm package` - **ALSO BROKEN** (confirmed in testing) + +**This means Helm v3.19.0 is completely unusable for StreamSpace.** + +**Solutions:** + +#### Option 1: Use kubectl-based Deployment ✅ RECOMMENDED for Helm v3.19.0 +We've created a Helm-free deployment script that uses raw Kubernetes manifests: + +```bash +./scripts/local-deploy-kubectl.sh +``` + +This script: +- ✅ Works with any Helm version (doesn't use Helm) +- ✅ Deploys all components (controller, API, UI, database) +- ✅ Creates RBAC, secrets, and services +- ✅ Uses the same local Docker images +- ✅ Perfect for Docker Desktop users stuck on Helm v3.19.0 + +**This is the recommended approach if you can't downgrade Helm.** + +#### Option 2: Downgrade Helm (Best Long-term Solution) +Downgrade to Helm v3.18.0 or earlier: + +**On macOS (using Homebrew):** +```bash +# Uninstall current version +brew uninstall helm + +# Install specific version +brew install helm@3.18.0 + +# Or use asdf for version management +asdf install helm 3.18.0 +asdf global helm 3.18.0 +``` + +**On Linux:** +```bash +# Download specific version +wget https://get.helm.sh/helm-v3.18.0-linux-amd64.tar.gz +tar -zxvf helm-v3.18.0-linux-amd64.tar.gz +sudo mv linux-amd64/helm /usr/local/bin/helm +``` + +**Note for Docker Desktop Users:** +If you're using Docker Desktop (macOS or Windows), Helm is bundled with the Kubernetes distribution and cannot be easily downgraded. In this case, **use the kubectl-based deployment** (Option 1) until Docker Desktop updates to a fixed Helm version. + +--- + +**Why Package/Template Workarounds Don't Work:** +Helm v3.19.0's bug is so severe that it affects **all chart loading operations**, including `helm package` and `helm template`. There is no workaround within Helm itself - you must either use kubectl-based deployment or downgrade Helm. + +**Verification:** +After installation, verify the deployment is working: +```bash +# Check pod status +kubectl get pods -n streamspace + +# Check helm release +helm status streamspace -n streamspace + +# Check logs +kubectl logs -n streamspace -l app.kubernetes.io/component=controller -f +``` + +--- + +## Image Pull Issues + +### Issue: ImagePullBackOff for local images + +**Symptoms:** +``` +NAME READY STATUS RESTARTS AGE +streamspace-controller-xxxxx 0/1 ImagePullBackOff 0 2m +``` + +**Cause:** +Kubernetes is trying to pull the image from a registry instead of using the local Docker image. + +**Solution:** + +1. **Verify images exist locally:** +```bash +docker images | grep streamspace +``` + +You should see: +``` +streamspace/streamspace-controller local ... +streamspace/streamspace-api local ... +streamspace/streamspace-ui local ... +``` + +2. **Ensure `imagePullPolicy` is set to `Never`:** + +The deployment script should set this automatically, but you can verify: +```bash +kubectl get deployment streamspace-controller -n streamspace -o jsonpath='{.spec.template.spec.containers[0].imagePullPolicy}' +``` + +Should output: `Never` + +3. **For Docker Desktop Kubernetes:** + +Make sure you're using the same Docker context: +```bash +# Check current context +docker context list + +# If needed, switch to default +docker context use default +``` + +4. **Manual fix if needed:** +```bash +helm upgrade streamspace ./chart \ + --namespace streamspace \ + --reuse-values \ + --set controller.image.pullPolicy=Never \ + --set api.image.pullPolicy=Never \ + --set ui.image.pullPolicy=Never +``` + +--- + +## Database Connection Issues + +### Issue: API or Controller can't connect to PostgreSQL + +**Symptoms:** +``` +Error: failed to connect to postgres: dial tcp: lookup streamspace-postgres: no such host +``` + +**Solutions:** + +1. **Verify PostgreSQL is running:** +```bash +kubectl get pods -n streamspace -l app.kubernetes.io/component=database +``` + +2. **Check PostgreSQL service:** +```bash +kubectl get svc -n streamspace -l app.kubernetes.io/component=database +``` + +3. **Verify connection from a test pod:** +```bash +kubectl run -it --rm debug --image=postgres:15 --restart=Never -n streamspace -- \ + psql -h streamspace-postgres -U streamspace -d streamspace +``` + +4. **Check PostgreSQL logs:** +```bash +kubectl logs -n streamspace -l app.kubernetes.io/component=database +``` + +5. **Verify password secret:** +```bash +kubectl get secret streamspace-secrets -n streamspace -o jsonpath='{.data.postgres-password}' | base64 -d +``` + +--- + +## CRD Installation Issues + +### Issue: CRDs not found + +**Symptoms:** +``` +Error from server (NotFound): the server could not find the requested resource (get sessions.stream.streamspace.io) +``` + +**Solutions:** + +1. **Manually install CRDs:** +```bash +kubectl apply -f ./chart/crds/ +``` + +2. **Verify CRDs are installed:** +```bash +kubectl get crds | grep streamspace +``` + +Expected output: +``` +sessions.stream.streamspace.io +templates.stream.streamspace.io +templaterepositories.stream.streamspace.io +connections.stream.streamspace.io +``` + +3. **Check CRD details:** +```bash +kubectl get crd sessions.stream.streamspace.io -o yaml +``` + +4. **Reinstall if needed:** +```bash +kubectl delete crd sessions.stream.streamspace.io templates.stream.streamspace.io +kubectl apply -f ./chart/crds/ +``` + +--- + +## Controller Issues + +### Issue: Controller not starting or crash looping + +**Symptoms:** +``` +NAME READY STATUS RESTARTS AGE +streamspace-controller-xxxxx 0/1 CrashLoopBackOff 5 5m +``` + +**Debugging Steps:** + +1. **Check controller logs:** +```bash +kubectl logs -n streamspace -l app.kubernetes.io/component=controller --tail=100 +``` + +2. **Check for RBAC issues:** +```bash +kubectl auth can-i get deployments --as=system:serviceaccount:streamspace:streamspace-controller -n streamspace +``` + +3. **Verify service account exists:** +```bash +kubectl get serviceaccount streamspace-controller -n streamspace +``` + +4. **Check resource limits:** +```bash +kubectl describe pod -n streamspace -l app.kubernetes.io/component=controller +``` + +5. **Increase verbosity:** +```bash +helm upgrade streamspace ./chart \ + --namespace streamspace \ + --reuse-values \ + --set controller.args.verbosity=2 +``` + +--- + +## Additional Resources + +- **Helm Documentation:** https://helm.sh/docs/ +- **Kubernetes Debugging:** https://kubernetes.io/docs/tasks/debug/ +- **StreamSpace Architecture:** [ARCHITECTURE.md](./ARCHITECTURE.md) +- **GitHub Issues:** https://github.com/streamspace/streamspace/issues + +For further assistance, please open an issue on GitHub with: +1. Output of `kubectl version` +2. Output of `helm version` +3. Relevant logs from affected components +4. Steps to reproduce the issue diff --git a/manifests/kubectl/rbac.yaml b/manifests/kubectl/rbac.yaml new file mode 100644 index 00000000..42454768 --- /dev/null +++ b/manifests/kubectl/rbac.yaml @@ -0,0 +1,197 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: streamspace-controller + namespace: streamspace + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: controller +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: streamspace-api + namespace: streamspace + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: api +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: streamspace-controller + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: controller +rules: + # Session resources + - apiGroups: ["stream.streamspace.io"] + resources: ["sessions"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["stream.streamspace.io"] + resources: ["sessions/status"] + verbs: ["get", "update", "patch"] + - apiGroups: ["stream.streamspace.io"] + resources: ["sessions/finalizers"] + verbs: ["update"] + + # Template resources + - apiGroups: ["stream.streamspace.io"] + resources: ["templates"] + verbs: ["get", "list", "watch"] + - apiGroups: ["stream.streamspace.io"] + resources: ["templates/status"] + verbs: ["get"] + + # TemplateRepository resources + - apiGroups: ["stream.streamspace.io"] + resources: ["templaterepositories"] + verbs: ["get", "list", "watch"] + + # Connection resources + - apiGroups: ["stream.streamspace.io"] + resources: ["connections"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["stream.streamspace.io"] + resources: ["connections/status"] + verbs: ["get", "update", "patch"] + + # Core K8s resources + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] + - apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create"] + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] + + # Apps resources + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] + - apiGroups: ["apps"] + resources: ["statefulsets"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + + # Networking resources + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: streamspace-controller + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: streamspace-controller +subjects: + - kind: ServiceAccount + name: streamspace-controller + namespace: streamspace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: streamspace-controller-leader-election + namespace: streamspace + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: controller +rules: + - apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: ["coordination.k8s.io"] + resources: ["leases"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["events"] + verbs: ["create", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: streamspace-controller-leader-election + namespace: streamspace + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: streamspace-controller-leader-election +subjects: + - kind: ServiceAccount + name: streamspace-controller + namespace: streamspace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: streamspace-api + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: api +rules: + # Read-only access to CRDs + - apiGroups: ["stream.streamspace.io"] + resources: ["sessions", "templates", "templaterepositories", "connections"] + verbs: ["get", "list", "watch"] + - apiGroups: ["stream.streamspace.io"] + resources: ["sessions/status", "templates/status", "connections/status"] + verbs: ["get"] + + # Access to pods for session management + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] + - apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] + + # Access to services + - apiGroups: [""] + resources: ["services"] + verbs: ["get", "list", "watch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: streamspace-api + labels: + app.kubernetes.io/name: streamspace + app.kubernetes.io/component: api +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: streamspace-api +subjects: + - kind: ServiceAccount + name: streamspace-api + namespace: streamspace diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..9d63f559 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,241 @@ +# StreamSpace Deployment Scripts + +This directory contains scripts for building and deploying StreamSpace locally. + +## Quick Start + +### 1. Build Local Images + +```bash +./scripts/local-build.sh +``` + +This builds Docker images for the controller, API, and UI. + +### 2. Deploy to Local Kubernetes + +**Choose the appropriate deployment method based on your Helm version:** + +#### If you have Helm v3.19.0 (Docker Desktop users) → Use kubectl + +```bash +./scripts/local-deploy-kubectl.sh +``` + +Helm v3.19.0 has a critical bug that breaks all chart operations. The kubectl-based script bypasses Helm entirely. + +#### If you have Helm v3.18.0 or earlier → Use Helm + +```bash +./scripts/local-deploy.sh +``` + +This uses the Helm chart for deployment. + +### 3. Check Your Helm Version + +```bash +helm version --short +``` + +- **v3.19.0 or later**: Use `local-deploy-kubectl.sh` +- **v3.18.0 or earlier**: Use `local-deploy.sh` + +## Script Descriptions + +### local-build.sh + +Builds all StreamSpace Docker images locally: +- `streamspace/streamspace-controller:local` +- `streamspace/streamspace-api:local` +- `streamspace/streamspace-ui:local` + +**Usage:** +```bash +./scripts/local-build.sh +``` + +**Options:** +- Set `VERSION=custom` to use a different tag + +### local-deploy.sh + +Deploys StreamSpace using Helm chart (for Helm v3.18.0 or earlier). + +**Usage:** +```bash +./scripts/local-deploy.sh +``` + +**Environment Variables:** +- `NAMESPACE`: Kubernetes namespace (default: `streamspace`) +- `RELEASE_NAME`: Helm release name (default: `streamspace`) +- `VERSION`: Image tag to use (default: `local`) + +**Requirements:** +- Helm v3.18.0 or earlier +- kubectl with cluster access +- Local Docker images built +- Kubernetes cluster (Docker Desktop, k3s, minikube, etc.) + +### local-deploy-kubectl.sh + +Deploys StreamSpace using raw Kubernetes manifests (Helm-free). + +**Usage:** +```bash +./scripts/local-deploy-kubectl.sh +``` + +**Environment Variables:** +- `NAMESPACE`: Kubernetes namespace (default: `streamspace`) +- `VERSION`: Image tag to use (default: `local`) + +**Requirements:** +- kubectl with cluster access +- Local Docker images built +- Kubernetes cluster (Docker Desktop, k3s, minikube, etc.) +- **Does NOT require Helm** - works with any Helm version + +**Why This Exists:** +- Helm v3.19.0 (bundled with Docker Desktop) has a critical bug +- Provides a Helm-free alternative for users who can't downgrade +- Uses the same manifests, just applies them directly with kubectl + +### local-teardown.sh + +Removes StreamSpace deployment and cleans up resources. + +**Usage:** +```bash +./scripts/local-teardown.sh +``` + +## Helm v3.19.0 Issue + +**Problem:** Helm v3.19.0 has a critical regression in the chart loader that makes it completely unusable for loading charts from directories. All operations fail: +- `helm lint` → fails +- `helm template` → fails +- `helm package` → fails +- `helm install` → fails + +**Affected Users:** +- Docker Desktop users on macOS/Windows (Helm is bundled) +- Anyone who upgraded to Helm v3.19.0 + +**Solutions:** +1. **Use `local-deploy-kubectl.sh`** (recommended) - bypasses Helm entirely +2. **Downgrade Helm** to v3.18.0 or earlier (if possible) + +**For Details:** +See `docs/DEPLOYMENT_TROUBLESHOOTING.md` for comprehensive troubleshooting. + +## Common Tasks + +### Access the UI + +```bash +kubectl port-forward -n streamspace svc/streamspace-ui 3000:80 +``` + +Then open: http://localhost:3000 + +### Access the API + +```bash +kubectl port-forward -n streamspace svc/streamspace-api 8000:8000 +``` + +Then open: http://localhost:8000 + +### View Logs + +```bash +# Controller +kubectl logs -n streamspace -l app.kubernetes.io/component=controller -f + +# API +kubectl logs -n streamspace -l app.kubernetes.io/component=api -f + +# UI +kubectl logs -n streamspace -l app.kubernetes.io/component=ui -f + +# Database +kubectl logs -n streamspace -l app.kubernetes.io/component=database -f +``` + +### Check Deployment Status + +```bash +kubectl get pods -n streamspace +kubectl get svc -n streamspace +kubectl get sessions -n streamspace +kubectl get templates -n streamspace +``` + +### Clean Up + +Using Helm (if you deployed with `local-deploy.sh`): +```bash +./scripts/local-teardown.sh +``` + +Using kubectl (if you deployed with `local-deploy-kubectl.sh`): +```bash +kubectl delete namespace streamspace +``` + +## Troubleshooting + +### Images Not Found + +Build images first: +```bash +./scripts/local-build.sh +``` + +Verify they exist: +```bash +docker images | grep streamspace +``` + +### Helm Chart Errors + +If using Helm v3.19.0: +```bash +# Switch to kubectl-based deployment +./scripts/local-deploy-kubectl.sh +``` + +If using older Helm: +```bash +# Check Helm version +helm version --short + +# Use Helm deployment +./scripts/local-deploy.sh +``` + +### Pods Not Starting + +Check pod status: +```bash +kubectl get pods -n streamspace +kubectl describe pod -n streamspace +kubectl logs -n streamspace +``` + +Common issues: +- ImagePullBackOff: Images not built or wrong pullPolicy +- CrashLoopBackOff: Check logs for errors +- Pending: Check resource availability + +### Complete Troubleshooting Guide + +See: `docs/DEPLOYMENT_TROUBLESHOOTING.md` + +## Support + +- Documentation: `docs/` +- Issues: https://github.com/streamspace/streamspace/issues +- Discussions: https://github.com/streamspace/streamspace/discussions diff --git a/scripts/local-deploy-kubectl.sh b/scripts/local-deploy-kubectl.sh new file mode 100755 index 00000000..f38f62b4 --- /dev/null +++ b/scripts/local-deploy-kubectl.sh @@ -0,0 +1,599 @@ +#!/usr/bin/env bash +# +# local-deploy-kubectl.sh - Deploy StreamSpace using kubectl (Helm-free) +# +# This script deploys StreamSpace without Helm, using raw Kubernetes manifests. +# Use this as a workaround for Helm v3.19.0 bugs or when Helm is unavailable. +# + +set -euo pipefail + +# Colors for output +COLOR_RESET='\033[0m' +COLOR_BOLD='\033[1m' +COLOR_GREEN='\033[32m' +COLOR_YELLOW='\033[33m' +COLOR_BLUE='\033[34m' +COLOR_RED='\033[31m' + +# Project configuration +PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +NAMESPACE="${NAMESPACE:-streamspace}" +VERSION="${VERSION:-local}" + +# Image configuration +CONTROLLER_IMAGE="${CONTROLLER_IMAGE:-streamspace/streamspace-controller:${VERSION}}" +API_IMAGE="${API_IMAGE:-streamspace/streamspace-api:${VERSION}}" +UI_IMAGE="${UI_IMAGE:-streamspace/streamspace-ui:${VERSION}}" +POSTGRES_IMAGE="${POSTGRES_IMAGE:-postgres:15-alpine}" + +# Helper functions +log() { + echo -e "${COLOR_BOLD}==>${COLOR_RESET} $*" +} + +log_success() { + echo -e "${COLOR_GREEN}✓${COLOR_RESET} $*" +} + +log_error() { + echo -e "${COLOR_RED}✗${COLOR_RESET} $*" >&2 +} + +log_info() { + echo -e "${COLOR_BLUE}→${COLOR_RESET} $*" +} + +log_warning() { + echo -e "${COLOR_YELLOW}⚠${COLOR_RESET} $*" +} + +# Check prerequisites +check_prerequisites() { + log "Checking prerequisites..." + + if ! command -v kubectl &> /dev/null; then + log_error "kubectl is not installed or not in PATH" + exit 1 + fi + + if ! kubectl cluster-info &> /dev/null; then + log_error "Cannot connect to Kubernetes cluster" + log_info "Make sure your kubeconfig is properly configured" + exit 1 + fi + + local context=$(kubectl config current-context 2>/dev/null || echo "unknown") + log_success "Connected to cluster: ${context}" +} + +# Check if images exist locally +check_images() { + log "Checking for locally built images..." + + local missing_images=0 + + for image in "streamspace/streamspace-controller" "streamspace/streamspace-api" "streamspace/streamspace-ui"; do + if docker images "${image}:${VERSION}" --format "{{.Repository}}:{{.Tag}}" | grep -q "${image}:${VERSION}"; then + log_success "Found ${image}:${VERSION}" + else + log_error "Missing ${image}:${VERSION}" + missing_images=$((missing_images + 1)) + fi + done + + if [ $missing_images -gt 0 ]; then + log_error "Missing ${missing_images} image(s). Run './scripts/local-build.sh' first." + exit 1 + fi +} + +# Create namespace +create_namespace() { + log "Creating namespace: ${NAMESPACE}" + + if kubectl get namespace "${NAMESPACE}" &> /dev/null; then + log_warning "Namespace ${NAMESPACE} already exists" + else + kubectl create namespace "${NAMESPACE}" + log_success "Namespace created" + fi +} + +# Apply CRDs +apply_crds() { + log "Applying Custom Resource Definitions..." + + kubectl apply -f "${PROJECT_ROOT}/chart/crds/" + log_success "CRDs applied" +} + +# Create secrets +create_secrets() { + log "Creating secrets..." + + if kubectl get secret streamspace-secrets -n "${NAMESPACE}" &> /dev/null; then + log_warning "Secret streamspace-secrets already exists" + else + kubectl create secret generic streamspace-secrets \ + -n "${NAMESPACE}" \ + --from-literal=postgres-password=streamspace \ + --from-literal=jwt-secret=$(openssl rand -base64 32) \ + --from-literal=api-key=$(openssl rand -hex 32) + log_success "Secrets created" + fi +} + +# Deploy PostgreSQL +deploy_postgresql() { + log "Deploying PostgreSQL..." + + cat </dev/null | wc -l || echo "0") + local total_pods=$(kubectl get pods -n "${NAMESPACE}" --no-headers 2>/dev/null | wc -l || echo "0") + + if [ "$ready_pods" -eq "$total_pods" ] && [ "$total_pods" -gt 0 ]; then + log_success "All pods are ready" + return 0 + fi + + log_info "Waiting... (${ready_pods}/${total_pods} pods ready)" + sleep $interval + elapsed=$((elapsed + interval)) + done + + log_warning "Timeout waiting for pods to be ready" + log_info "Check pod status with: kubectl get pods -n ${NAMESPACE}" +} + +# Show deployment status +show_status() { + log "Deployment Status:" + echo "" + + log_info "Pods:" + kubectl get pods -n "${NAMESPACE}" -o wide + echo "" + + log_info "Services:" + kubectl get svc -n "${NAMESPACE}" + echo "" +} + +# Show access instructions +show_access_info() { + echo "" + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" + echo -e "${COLOR_BOLD} Access Instructions${COLOR_RESET}" + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" + echo "" + + log_info "Port-forward UI (in a separate terminal):" + echo " kubectl port-forward -n ${NAMESPACE} svc/streamspace-ui 3000:80" + echo " Then access: http://localhost:3000" + echo "" + + log_info "Port-forward API (in a separate terminal):" + echo " kubectl port-forward -n ${NAMESPACE} svc/streamspace-api 8000:8000" + echo " Then access: http://localhost:8000" + echo "" + + log_info "View logs:" + echo " Controller: kubectl logs -n ${NAMESPACE} -l app.kubernetes.io/component=controller -f" + echo " API: kubectl logs -n ${NAMESPACE} -l app.kubernetes.io/component=api -f" + echo " UI: kubectl logs -n ${NAMESPACE} -l app.kubernetes.io/component=ui -f" + echo " Database: kubectl logs -n ${NAMESPACE} -l app.kubernetes.io/component=database -f" + echo "" + + log_info "When finished testing:" + echo " kubectl delete namespace ${NAMESPACE}" + echo "" +} + +# Main execution +main() { + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" + echo -e "${COLOR_BOLD} StreamSpace kubectl Deployment${COLOR_RESET}" + echo -e "${COLOR_BOLD} (Helm-free alternative)${COLOR_RESET}" + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" + echo "" + echo -e "${COLOR_BLUE}Namespace:${COLOR_RESET} ${NAMESPACE}" + echo -e "${COLOR_BLUE}Version:${COLOR_RESET} ${VERSION}" + echo "" + + check_prerequisites + check_images + create_namespace + apply_crds + create_secrets + deploy_postgresql + deploy_controller + deploy_api + deploy_ui + wait_for_pods + show_status + show_access_info + + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" + log_success "Deployment complete!" + echo -e "${COLOR_BOLD}═══════════════════════════════════════════════════${COLOR_RESET}" +} + +# Run main function +main "$@" diff --git a/scripts/local-deploy.sh b/scripts/local-deploy.sh index 975d442f..417a0722 100755 --- a/scripts/local-deploy.sh +++ b/scripts/local-deploy.sh @@ -129,29 +129,63 @@ deploy_helm() { log_info "Chart directory contents:" ls -la "${CHART_PATH}/" 2>&1 | head -10 - # Validate chart with helm lint - log_info "Validating chart with helm lint..." - if ! helm lint "${CHART_PATH}"; then - log_error "Helm chart validation failed!" - exit 1 + # Workaround for Helm v3.19.0: Package chart first, then install from .tgz + # This avoids the directory loading bug in v3.19.0 + local helm_version=$(helm version --short 2>/dev/null | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown") + local use_package_workaround=false + + if [[ "${helm_version}" == "v3.19."* ]] || [[ "${FORCE_PACKAGE:-false}" == "true" ]]; then + log_warning "Detected Helm ${helm_version} - using package workaround for chart loading bug" + use_package_workaround=true fi - log_success "Chart validation passed" - # Test if Helm can package the chart - log_info "Testing chart packaging..." - local temp_dir=$(mktemp -d) - if helm package "${CHART_PATH}" -d "${temp_dir}" &> /dev/null; then - log_success "Chart packaging test passed" - rm -rf "${temp_dir}" - else - log_warning "Chart packaging test failed (may not be critical)" - rm -rf "${temp_dir}" + # Try validation only if not using package workaround + if [ "${use_package_workaround}" = false ] && [ "${SKIP_LINT:-false}" != "true" ]; then + log_info "Validating chart with helm lint..." + if helm lint "${CHART_PATH}" 2>&1 | tee /tmp/helm-lint.log; then + log_success "Chart validation passed" + else + log_warning "Helm lint reported errors (this may be a Helm v3.19.0 issue)" + log_info "Will use package workaround for installation" + use_package_workaround=true + fi + fi + + # Prepare chart for installation + local chart_ref="${CHART_PATH}" + local temp_dir="" + + if [ "${use_package_workaround}" = true ]; then + log_info "Packaging chart to work around Helm v3.19.0 directory loading bug..." + temp_dir=$(mktemp -d) + + if helm package "${CHART_PATH}" -d "${temp_dir}" 2>&1 | tee /tmp/helm-package.log; then + # Find the packaged chart file + local chart_package=$(find "${temp_dir}" -name "streamspace-*.tgz" | head -1) + if [ -n "${chart_package}" ]; then + chart_ref="${chart_package}" + log_success "Chart packaged successfully: $(basename ${chart_package})" + else + log_error "Chart packaging failed - package file not found" + log_info "Package output:" + cat /tmp/helm-package.log + rm -rf "${temp_dir}" + exit 1 + fi + else + log_error "Chart packaging failed" + log_info "This is a critical Helm v3.19.0 bug. Please downgrade Helm to v3.18.0 or earlier." + log_info "See docs/DEPLOYMENT_TROUBLESHOOTING.md for detailed instructions." + rm -rf "${temp_dir}" + exit 1 + fi fi # Check if release exists if helm status "${RELEASE_NAME}" -n "${NAMESPACE}" &> /dev/null; then log_info "Release exists, upgrading..." - helm upgrade "${RELEASE_NAME}" "${CHART_PATH}" \ + log_info "Running: helm upgrade ${RELEASE_NAME} ${chart_ref}" + helm upgrade "${RELEASE_NAME}" "${chart_ref}" \ --namespace "${NAMESPACE}" \ --set controller.image.tag="${VERSION}" \ --set controller.image.pullPolicy=Never \ @@ -165,8 +199,8 @@ deploy_helm() { --timeout 5m else log_info "Installing fresh release..." - log_info "Running: helm install ${RELEASE_NAME} ${CHART_PATH}" - helm install "${RELEASE_NAME}" "${CHART_PATH}" \ + log_info "Running: helm install ${RELEASE_NAME} ${chart_ref}" + helm install "${RELEASE_NAME}" "${chart_ref}" \ --namespace "${NAMESPACE}" \ --create-namespace \ --set controller.image.tag="${VERSION}" \ @@ -182,6 +216,12 @@ deploy_helm() { --timeout 5m fi + # Clean up temporary directory if we created one + if [ -n "${temp_dir}" ] && [ -d "${temp_dir}" ]; then + rm -rf "${temp_dir}" + log_info "Cleaned up temporary package directory" + fi + log_success "Helm deployment complete" }