#!/usr/bin/env bash # deploy-plugin-via-volume.sh # # Copies the built plugin into the shared PVC so Headlamp picks it up. # Uses a temporary Kubernetes pod to write to the PVC — the CI runner # does NOT need the PVC mounted locally. # # Usage: # scripts/deploy-plugin-via-volume.sh # # Environment: # HEADLAMP_NAMESPACE — namespace where Headlamp runs (default: kube-system) # HEADLAMP_DEPLOY — Headlamp deployment name (default: headlamp) set -euo pipefail REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" HEADLAMP_NAMESPACE="${HEADLAMP_NAMESPACE:-kube-system}" HEADLAMP_DEPLOY="${HEADLAMP_DEPLOY:-headlamp}" # The deployed directory name must match the plugin's registered name. # PR #56 aligns registerPluginSettings to "polaris"; the directory must match. PLUGIN_DIR_NAME="polaris" DIST_DIR="$REPO_ROOT/dist" if [ ! -d "$DIST_DIR" ]; then echo "ERROR: dist/ not found. Run 'npm run build' first." >&2 exit 1 fi echo "Deploying plugin to shared volume via temporary pod..." echo " Source: $DIST_DIR" echo " PVC: headlamp-plugins" echo " Plugin: $PLUGIN_DIR_NAME" # Create tarball of plugin dist + package.json TAR_FILE=$(mktemp /tmp/plugin-XXXXXX.tar.gz) tar -czf "$TAR_FILE" -C "$DIST_DIR" . -C "$REPO_ROOT" package.json echo " Tarball: $TAR_FILE ($(du -h "$TAR_FILE" | cut -f1))" # Find the node where Headlamp is running — the PVC is ReadWriteOnce so # the deploy pod must land on the same node to mount it. HEADLAMP_NODE=$(kubectl get pods -n "$HEADLAMP_NAMESPACE" \ -l "app.kubernetes.io/name=headlamp" \ -o jsonpath='{.items[0].spec.nodeName}' 2>/dev/null || true) if [ -z "$HEADLAMP_NODE" ]; then HEADLAMP_NODE=$(kubectl get pods -n "$HEADLAMP_NAMESPACE" \ -l "app.kubernetes.io/instance=headlamp" \ -o jsonpath='{.items[0].spec.nodeName}' 2>/dev/null || true) fi if [ -n "$HEADLAMP_NODE" ]; then echo " Headlamp node: $HEADLAMP_NODE (scheduling deploy job there)" NODE_SELECTOR="\"nodeName\": \"$HEADLAMP_NODE\"," else echo " WARNING: Could not determine Headlamp node" NODE_SELECTOR="" fi # Clean up any previous deploy resources kubectl delete job plugin-deploy -n "$HEADLAMP_NAMESPACE" --ignore-not-found 2>/dev/null || true kubectl delete configmap plugin-tarball -n "$HEADLAMP_NAMESPACE" --ignore-not-found 2>/dev/null || true sleep 2 # Store the tarball in a ConfigMap (binary-safe via --from-file) echo "Creating ConfigMap with plugin tarball..." kubectl create configmap plugin-tarball \ -n "$HEADLAMP_NAMESPACE" \ --from-file=plugin.tar.gz="$TAR_FILE" # Create a Job that extracts the tarball from the ConfigMap to the PVC echo "Starting deploy job..." kubectl apply -n "$HEADLAMP_NAMESPACE" -f - </dev/null || true # Clean up kubectl delete job plugin-deploy -n "$HEADLAMP_NAMESPACE" --ignore-not-found 2>/dev/null || true kubectl delete configmap plugin-tarball -n "$HEADLAMP_NAMESPACE" --ignore-not-found 2>/dev/null || true rm -f "$TAR_FILE" # Restart Headlamp to pick up the new plugin echo "Restarting Headlamp deployment to load plugin..." kubectl rollout restart "deployment/$HEADLAMP_DEPLOY" -n "$HEADLAMP_NAMESPACE" kubectl rollout status "deployment/$HEADLAMP_DEPLOY" -n "$HEADLAMP_NAMESPACE" --timeout=120s echo "Plugin deployed successfully."