fix(e2e): replace helm upgrade with kubectl patch to avoid cluster RBAC

The CI runner SA cannot access cluster-scoped resources (ClusterRole,
ClusterRoleBinding) needed by helm upgrade's 3-way merge. Replace the
helm upgrade step with kubectl patch commands that add the shared volume
mount directly to the Headlamp deployment.

This eliminates the need for cluster-admin intervention:
- kubectl patch adds PVC volume + volumeMount to the deployment
- kubectl set env configures the plugins directory
- kubectl rollout status waits for the update

Also removes the now-unnecessary ClusterRole/ClusterRoleBinding from the
RBAC manifest — only namespace-scoped Role/RoleBinding is needed.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
2026-03-17 17:07:38 +00:00
parent d5d16b2fe3
commit e679216660
2 changed files with 45 additions and 43 deletions
+35 -13
View File
@@ -35,23 +35,45 @@ jobs:
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Setup Helm
uses: azure/setup-helm@v4
- name: Add Headlamp Helm repo
run: helm repo add headlamp https://kubernetes-sigs.github.io/headlamp/ && helm repo update
- name: Ensure PVC exists
run: kubectl apply -f deployment/headlamp-plugins-pvc.yaml
- name: Upgrade Headlamp with shared volume mount
- name: Patch Headlamp deployment with shared volume mount
run: |
helm upgrade headlamp headlamp/headlamp \
--namespace "$HEADLAMP_NAMESPACE" \
--reuse-values \
-f deployment/headlamp-e2e-values.yaml \
--set config.sessionTTL=1 \
--wait --timeout 120s
NS="$HEADLAMP_NAMESPACE"
DEPLOY="$HEADLAMP_DEPLOY"
# Add the PVC volume if not already present
HAS_VOL=$(kubectl get deploy "$DEPLOY" -n "$NS" \
-o jsonpath='{.spec.template.spec.volumes[?(@.name=="plugins")].name}')
if [ -z "$HAS_VOL" ]; then
kubectl patch deploy "$DEPLOY" -n "$NS" --type=json -p '[
{"op":"add","path":"/spec/template/spec/volumes/-","value":{
"name":"plugins",
"persistentVolumeClaim":{"claimName":"headlamp-plugins"}
}}
]'
fi
# Add the volume mount to the first container if not already present
HAS_MOUNT=$(kubectl get deploy "$DEPLOY" -n "$NS" \
-o jsonpath='{.spec.template.spec.containers[0].volumeMounts[?(@.name=="plugins")].name}')
if [ -z "$HAS_MOUNT" ]; then
kubectl patch deploy "$DEPLOY" -n "$NS" --type=json -p '[
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{
"name":"plugins",
"mountPath":"/headlamp/plugins",
"readOnly":true
}}
]'
fi
# Set the plugins directory via env var
kubectl set env deploy/"$DEPLOY" -n "$NS" \
HEADLAMP_CONFIG_PLUGIN_DIR=/headlamp/plugins
# Wait for rollout
kubectl rollout status deploy/"$DEPLOY" -n "$NS" --timeout=120s
- name: Deploy plugin via shared volume
run: scripts/deploy-plugin-via-volume.sh
+10 -30
View File
@@ -2,37 +2,14 @@
# RBAC for the GitHub Actions CI runner to perform E2E test setup.
# CI-only test fixture — NOT for production use.
#
# The Headlamp Helm chart manages cluster-scoped resources (ClusterRole,
# ClusterRoleBinding). The CI runner SA needs cluster-level read/write on
# these resources for `helm upgrade` to succeed, plus namespace-scoped
# permissions in kube-system for PVCs, pods, Helm secrets, etc.
# Grants the ARC runner service account namespace-scoped permissions in
# kube-system to patch the Headlamp deployment (add shared volume mount),
# manage PVCs, run temporary pods, and restart deployments.
#
# No cluster-scoped permissions needed — the E2E workflow uses kubectl patch
# instead of helm upgrade, avoiding the need to read ClusterRole/ClusterRoleBinding.
#
# Apply with: kubectl apply -f deployment/e2e-ci-runner-rbac.yaml
# --- Cluster-scoped permissions (for Headlamp Helm chart resources) ---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: e2e-ci-runner
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles", "clusterrolebindings"]
verbs: ["get", "list", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: e2e-ci-runner-binding
subjects:
- kind: ServiceAccount
name: local-ubuntu-latest-gha-rs-no-permission
namespace: arc-runners
roleRef:
kind: ClusterRole
name: e2e-ci-runner
apiGroup: rbac.authorization.k8s.io
---
# --- Namespace-scoped permissions (kube-system) ---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
@@ -50,7 +27,10 @@ rules:
verbs: ["create", "get"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "patch"]
verbs: ["get", "list", "patch", "watch"]
- apiGroups: ["apps"]
resources: ["deployments/scale"]
verbs: ["patch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "create", "update", "patch", "delete"]