refactor(hermes-triage-demo): ConfigMap fixture replaces Longhorn PVC

- Pipeline ensures the fixture ConfigMap and seeds unhealthy via patch-file
- Test-runner mounts the ConfigMap read-only; no storage attach involved
- New hermes-demo-repair SA + Role scoped to patching only the fixture CM
- Removes the fixture PVC (Flux prunes it)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jenkins 2026-08-05 17:42:10 -03:00
parent 3e6783e44d
commit 167ab91b60
4 changed files with 64 additions and 38 deletions

View File

@ -1,17 +0,0 @@
# services/hermes-triage-demo/fixture-pvc.yaml
# Single-file demo fixture: holds one state value ("healthy"/"unhealthy").
# The Jenkins test-runner reads it; the Ariadne repair Job writes it back to healthy.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: hermes-triage-demo-fixture
namespace: hermes-triage-demo
labels:
app.kubernetes.io/part-of: hermes-triage-demo
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 100Mi

View File

@ -3,5 +3,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization kind: Kustomization
resources: resources:
- namespace.yaml - namespace.yaml
- fixture-pvc.yaml
- rbac.yaml - rbac.yaml

View File

@ -1,8 +1,19 @@
# services/hermes-triage-demo/rbac.yaml # services/hermes-triage-demo/rbac.yaml
# Lets Jenkins agent pods (SA jenkins/jenkins) create and observe the demo # Two scoped grants:
# test-runner Job in this namespace only. The Ariadne repair path needs no # 1. Jenkins agent pods (SA jenkins/jenkins) create and observe the demo
# grant here: its ariadne-job-spawner ClusterRole already covers Job # test-runner Job and manage the fixture ConfigMap (ensure + seed).
# create/watch, and the repair pod itself only mounts the fixture PVC. # 2. The Ariadne-created repair Job runs as SA hermes-demo-repair, which can
# patch only the fixture ConfigMap back to healthy.
# The Ariadne repair path needs no Job-create grant here: its
# ariadne-job-spawner ClusterRole already covers Job create/watch.
apiVersion: v1
kind: ServiceAccount
metadata:
name: hermes-demo-repair
namespace: hermes-triage-demo
labels:
app.kubernetes.io/part-of: hermes-triage-demo
---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: Role kind: Role
metadata: metadata:
@ -20,6 +31,13 @@ rules:
- apiGroups: [""] - apiGroups: [""]
resources: ["pods/log"] resources: ["pods/log"]
verbs: ["get"] verbs: ["get"]
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["hermes-triage-demo-fixture"]
verbs: ["get", "patch"]
--- ---
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding kind: RoleBinding
@ -36,3 +54,32 @@ subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: jenkins name: jenkins
namespace: jenkins namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: demo-repair
namespace: hermes-triage-demo
labels:
app.kubernetes.io/part-of: hermes-triage-demo
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["hermes-triage-demo-fixture"]
verbs: ["get", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: demo-repair
namespace: hermes-triage-demo
labels:
app.kubernetes.io/part-of: hermes-triage-demo
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: demo-repair
subjects:
- kind: ServiceAccount
name: hermes-demo-repair
namespace: hermes-triage-demo

View File

@ -492,7 +492,12 @@ data:
def buildNum = '' + env.BUILD_NUMBER def buildNum = '' + env.BUILD_NUMBER
def incidentId = 'hermes-triage-demo/' + buildNum def incidentId = 'hermes-triage-demo/' + buildNum
def jobName = 'hermes-demo-test-' + buildNum def jobName = 'hermes-demo-test-' + buildNum
def seed = params.SEED_FAILURE ? 'true' : 'false' sh 'kubectl -n hermes-triage-demo get configmap hermes-triage-demo-fixture || kubectl -n hermes-triage-demo create configmap hermes-triage-demo-fixture --from-literal=state=healthy'
if (params.SEED_FAILURE) {
writeFile file: 'seed.json', text: '{"data":{"state":"unhealthy"}}'
sh 'kubectl -n hermes-triage-demo patch configmap hermes-triage-demo-fixture --type merge --patch-file seed.json'
echo 'Demo failure armed: fixture state set to unhealthy'
}
def manifest = [ def manifest = [
'apiVersion: batch/v1', 'apiVersion: batch/v1',
'kind: Job', 'kind: Job',
@ -520,29 +525,21 @@ data:
' env:', ' env:',
' - name: INCIDENT_ID', ' - name: INCIDENT_ID',
' value: "' + incidentId + '"', ' value: "' + incidentId + '"',
' - name: SEED_FAILURE',
' value: "' + seed + '"',
' command:', ' command:',
' - sh', ' - sh',
' - -c', ' - -c',
' - |', ' - |',
' STATE_FILE=/fixture/state', ' STATE=$(cat /fixture/state)',
' if [ "$SEED_FAILURE" = "true" ]; then',
' echo unhealthy > "$STATE_FILE"',
' fi',
' if [ ! -f "$STATE_FILE" ]; then',
' echo healthy > "$STATE_FILE"',
' fi',
' STATE=$(cat "$STATE_FILE")',
' if [ "$STATE" = "healthy" ]; then', ' if [ "$STATE" = "healthy" ]; then',
' echo "{\\\\"event\\\\":\\\\"hermes_demo_test_pass\\\\",\\\\"incident_id\\\\":\\\\"$INCIDENT_ID\\\\",\\\\"message\\\\":\\\\"fixture state healthy\\\\"}"', ' echo "{\\"event\\":\\"hermes_demo_test_pass\\",\\"incident_id\\":\\"$INCIDENT_ID\\",\\"message\\":\\"fixture state healthy\\"}"',
' exit 0', ' exit 0',
' fi', ' fi',
' echo "{\\\\"event\\\\":\\\\"hermes_demo_test_failure\\\\",\\\\"incident_id\\\\":\\\\"$INCIDENT_ID\\\\",\\\\"classification_hint\\\\":\\\\"demo_fixture_unhealthy\\\\",\\\\"message\\\\":\\\\"expected fixture state healthy; found $STATE\\\\"}"', ' echo "{\\"event\\":\\"hermes_demo_test_failure\\",\\"incident_id\\":\\"$INCIDENT_ID\\",\\"classification_hint\\":\\"demo_fixture_unhealthy\\",\\"message\\":\\"expected fixture state healthy; found $STATE\\"}"',
' exit 1', ' exit 1',
' volumeMounts:', ' volumeMounts:',
' - name: fixture', ' - name: fixture',
' mountPath: /fixture', ' mountPath: /fixture',
' readOnly: true',
' resources:', ' resources:',
' requests:', ' requests:',
' cpu: 25m', ' cpu: 25m',
@ -552,10 +549,10 @@ data:
' memory: 32Mi', ' memory: 32Mi',
' volumes:', ' volumes:',
' - name: fixture', ' - name: fixture',
' persistentVolumeClaim:', ' configMap:',
' claimName: hermes-triage-demo-fixture' ' name: hermes-triage-demo-fixture'
] ]
writeFile file: 'test-runner-job.yaml', text: manifest.join('\\n') + '\\n' writeFile file: 'test-runner-job.yaml', text: manifest.join('\n') + '\n'
sh 'kubectl -n hermes-triage-demo create -f test-runner-job.yaml' sh 'kubectl -n hermes-triage-demo create -f test-runner-job.yaml'
def verdict = 'unknown' def verdict = 'unknown'
timeout(time: 3, unit: 'MINUTES') { timeout(time: 3, unit: 'MINUTES') {