Files
headlamp-polaris-plugin/scripts/deploy-plugin-via-volume.sh
T
Hugh Hackman 77d87db614 fix(e2e): schedule deploy pod on same node as Headlamp
The headlamp-plugins PVC is ReadWriteOnce, so the temporary deploy
pod must run on the same node as the Headlamp pod to mount it.
Look up the Headlamp pod's node and set nodeName in the pod spec.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-17 17:12:24 +00:00

102 lines
3.5 KiB
Bash
Executable File

#!/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
# Fallback: try by deployment label
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 pod there)"
NODE_OVERRIDE="\"nodeName\": \"$HEADLAMP_NODE\","
else
echo " WARNING: Could not determine Headlamp node, deploy pod may fail if PVC is ReadWriteOnce"
NODE_OVERRIDE=""
fi
# Clean up any previous deploy pod
kubectl delete pod plugin-deploy -n "$HEADLAMP_NAMESPACE" --ignore-not-found --wait=false 2>/dev/null || true
sleep 2
# Run a temporary pod that mounts the PVC and receives the tarball via stdin
echo "Starting deploy pod..."
kubectl run plugin-deploy \
--rm -i \
--restart=Never \
--image=busybox:1.36 \
--namespace="$HEADLAMP_NAMESPACE" \
--overrides="{
\"spec\": {
${NODE_OVERRIDE}
\"containers\": [{
\"name\": \"plugin-deploy\",
\"image\": \"busybox:1.36\",
\"stdin\": true,
\"command\": [\"sh\", \"-c\",
\"rm -rf /plugins/${PLUGIN_DIR_NAME} && mkdir -p /plugins/${PLUGIN_DIR_NAME} && tar -xzf - -C /plugins/${PLUGIN_DIR_NAME} && echo Files deployed: && ls -la /plugins/${PLUGIN_DIR_NAME}/\"
],
\"volumeMounts\": [{
\"name\": \"plugins\",
\"mountPath\": \"/plugins\"
}]
}],
\"volumes\": [{
\"name\": \"plugins\",
\"persistentVolumeClaim\": {
\"claimName\": \"headlamp-plugins\"
}
}]
}
}" < "$TAR_FILE"
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."