From 13899a37c0ba2b744c21df148c20c42f4646eb64 Mon Sep 17 00:00:00 2001 From: Jayapriya Pai Date: Mon, 1 Jun 2026 13:42:09 +0530 Subject: [PATCH] [BUGFIX] Add e2e test for file-storage multi-replica dashboard sync Add Kuttl test replica-file-sync that deploys Perses with file DB and three StatefulSet replicas, then asserts the dashboard exists on each pod via direct port-forward (not only through the ClusterIP Service). Related-to: #409 Signed-off-by: Jayapriya Pai --- test/e2e/replica-file-sync/00-assert.yaml | 34 ++++++++++++++++ test/e2e/replica-file-sync/00-install.yaml | 21 ++++++++++ test/e2e/replica-file-sync/01-install.yaml | 43 ++++++++++++++++++++ test/e2e/replica-file-sync/02-assert.yaml | 46 ++++++++++++++++++++++ 4 files changed, 144 insertions(+) create mode 100644 test/e2e/replica-file-sync/00-assert.yaml create mode 100644 test/e2e/replica-file-sync/00-install.yaml create mode 100644 test/e2e/replica-file-sync/01-install.yaml create mode 100644 test/e2e/replica-file-sync/02-assert.yaml diff --git a/test/e2e/replica-file-sync/00-assert.yaml b/test/e2e/replica-file-sync/00-assert.yaml new file mode 100644 index 0000000..45665ca --- /dev/null +++ b/test/e2e/replica-file-sync/00-assert.yaml @@ -0,0 +1,34 @@ +# Step 2: wait for all pods to be ready. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 300 +--- +apiVersion: perses.dev/v1alpha2 +kind: Perses +metadata: + name: perses-multi-replica +status: + conditions: + - type: Available + status: "True" + reason: Reconciled + - type: Degraded + status: "False" + reason: Reconciled +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: perses-multi-replica-config +--- +apiVersion: v1 +kind: Service +metadata: + name: perses-multi-replica +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: perses-multi-replica +status: + readyReplicas: 3 diff --git a/test/e2e/replica-file-sync/00-install.yaml b/test/e2e/replica-file-sync/00-install.yaml new file mode 100644 index 0000000..6cbfc63 --- /dev/null +++ b/test/e2e/replica-file-sync/00-install.yaml @@ -0,0 +1,21 @@ +# Step 1: Perses with file storage and replicas > 1 (separate PVC per pod). +apiVersion: perses.dev/v1alpha2 +kind: Perses +metadata: + name: perses-multi-replica + labels: + app.kubernetes.io/instance: perses-multi-replica +spec: + replicas: 3 + metadata: + labels: + instance: perses-multi-replica + config: + database: + file: + extension: yaml + folder: /perses + containerPort: 8080 + resources: + requests: + memory: 128Mi diff --git a/test/e2e/replica-file-sync/01-install.yaml b/test/e2e/replica-file-sync/01-install.yaml new file mode 100644 index 0000000..bf84d30 --- /dev/null +++ b/test/e2e/replica-file-sync/01-install.yaml @@ -0,0 +1,43 @@ +# Step 3: PersesDashboard synced to the Perses instance via instanceSelector. +apiVersion: perses.dev/v1alpha2 +kind: PersesDashboard +metadata: + name: multi-replica-dashboard +spec: + instanceSelector: + matchLabels: + app.kubernetes.io/instance: perses-multi-replica + config: + display: + name: Multi Replica Dashboard + duration: 5m + panels: + testPanel: + kind: Panel + spec: + display: + name: Test Panel + plugin: + kind: TimeSeriesChart + spec: {} + queries: + - kind: TimeSeriesQuery + spec: + plugin: + kind: PrometheusTimeSeriesQuery + spec: + query: up + layouts: + - kind: Grid + spec: + display: + title: Row 1 + collapse: + open: true + items: + - x: 0 + "y": 0 + width: 24 + height: 6 + content: + "$ref": "#/spec/panels/testPanel" diff --git a/test/e2e/replica-file-sync/02-assert.yaml b/test/e2e/replica-file-sync/02-assert.yaml new file mode 100644 index 0000000..f8a8614 --- /dev/null +++ b/test/e2e/replica-file-sync/02-assert.yaml @@ -0,0 +1,46 @@ +# Step 4: list dashboards on each pod (not via the Service). +# Strict: the first poll where any replica lists the dashboard, all replicas must. +# Step timeout is short: Kuttl retries failed asserts, so keep each run fast. +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +timeout: 15 +commands: + - script: | + STS=perses-multi-replica + DASHBOARD=multi-replica-dashboard + URL="/api/v1/projects/${NAMESPACE}/dashboards" + + kubectl port-forward -n "$NAMESPACE" "pod/${STS}-0" 18080:8080 & + PF0=$! + kubectl port-forward -n "$NAMESPACE" "pod/${STS}-1" 18081:8080 & + PF1=$! + kubectl port-forward -n "$NAMESPACE" "pod/${STS}-2" 18082:8080 & + PF2=$! + trap 'kill $PF0 $PF1 $PF2 2>/dev/null' EXIT + sleep 2 + + HAVE=0 + for wait in $(seq 1 20); do + HAVE=0 + for PORT in 18080 18081 18082; do + if curl -sf --connect-timeout 2 --max-time 3 \ + "http://localhost:${PORT}${URL}" 2>/dev/null | grep -q "$DASHBOARD"; then + HAVE=$((HAVE + 1)) + fi + done + if [ "$HAVE" -gt 0 ]; then + break + fi + sleep 1 + done + + if [ "$HAVE" -eq 0 ]; then + echo "FAIL: dashboard never appeared on any replica" + exit 1 + fi + if [ "$HAVE" -eq 3 ]; then + echo "Dashboard listed on all replicas" + exit 0 + fi + echo "FAIL: dashboard on ${HAVE}/3 replicas" + exit 1