QA Use Cases — CRC / OpenShift
Tool page: workload-cluster.md. CRC (OpenShift 4.22.7) runs on the m4 and hosts the workload plane: OpenShift GitOps, the agentops platform’s second instance, the service-health E2E surface. CRC is intentionally STOPPED at the time of writing — every story here is framed when CRC is running, and a stopped CRC makes each story not-run, never failed. Start discipline: the CRC-start checklist (goal record) governs, including its preconditions (not inside the Mon/Wed evening chess auto-stop window; mini side healthy first — CRC consumes the mini’s LDAP, Vault, and Harbor).
Admin stories
CRC-A1 — Cluster and console reachable, end to end [CLI]
- Persona: Platform admin.
- Steps: after a start, prove the tunnel path end to end: console health and API health through the tunnel — a bound port alone never counts (source: CRC-start checklist, “Tunnel proof end-to-end”).
- Expected: console at
console.crc.rhels.comand the API both answer healthy through the tunnel. - Assert: console health endpoint →
200; API/healthz→200; both fetched through the tunnel address with proxy bypass, per the checklist’s probe form.
CRC-A2 — OAuth providers: LDAP primary, htpasswd break-glass [browser]
- Persona: Platform admin.
- Steps: open the console login; confirm the
agentops-ldapprovider is offered and works (the IDN-U1 bind’s console form); confirm the htpasswddeveloperaccount still exists as break-glass. - Expected: both providers present;
developeris break-glass only — the daily path is LDAP (source: service-directory.md — console row; identity.md, break-glass paths). - Assert: console login page lists
agentops-ldap;oc get oauth clusterproviders ⊇{agentops-ldap, htpasswd}; adeveloperlogin succeeds (used only by this check, on the admin’s word — the fixture cadence is per-start, not per-run; see Gaps).
CRC-A3 — OpenShift group-sync projection freshness [config/API]
- Persona: Platform admin.
- Steps: read the
openshift-group-syncCronJob’s last run and the projected OpenShift groups. - Expected: the projection runs every 30 minutes (rfc2307) over the recorded 9-group whitelist, no prune; projected memberships equal the directory’s (source: lab record — periodic group sync delivery 2026-10-14; identity.md, “Projection into OpenShift”).
- Assert: last successful run age <=
35m; OpenShift group set == the whitelist set; sampled group’s users == the LDAP group’s members.
CRC-A4 — OpenShift GitOps census [config/API]
- Persona: Platform admin.
- Steps: the ARG-A1 census, CRC edition: every
Application in
openshift-gitops. - Expected: all Synced/Healthy, including the platform apps (observability, logging, vault-access, security, agentops) (source: tools/argocd.md — CRC layout).
- Assert: per ARG-A1: every item Synced + Healthy; the census names its exceptions.
CRC-A5 — Vault Kubernetes auth from CRC [config/API]
- Persona: Platform admin.
- Steps: confirm a CRC tenant’s VSO delivery is live (VLT-U2’s CRC leg) and the Vault auth role for CRC service accounts authenticates.
- Expected: tenants SYNCED; the auth path the namespace
chart wires (
vault-authServiceAccount +VaultAuth, role convention<bsn>-role) works for a created namespace (source: vault.md, tenant pattern; namespace-service.md, step 8). - Assert: per VLT-U2 on the CRC side; a token issued via the k8s auth method for a tenant SA can read exactly its one path (VLT-U3’s negative applies here too).
CRC-A6 — The E2E cycle is the platform’s own story [config/API]
- Persona: Platform admin (the 6-hourly trigger runs this persona unattended).
- Steps: read the latest E2E run manifest and the observer’s stage table.
- Expected: the cycle grades its stages — runner, build-sign, alert-delivery, alert-bridge, vault-secret, kyverno, readiness, logs, metrics, cert — and a completed run reaches 18/18 stage passes, as the proof cycles did (source: E2E design + observer record; proof runs 2026-10-25/26 graded 18/18).
- Assert: latest completed manifest: every stage present with a verdict; known defect to assert around: an hourly grading that lands mid-cycle can mis-grade in-flight stages (lab-agentops#27) and step-B pushes can hit non-fast-forward (#29) — both are tracked defects, reported as such, not suite noise.
Status — 2026-11-01: latest cycle 2026-11-01 06:32Z, manifest
e2e-20261101063208: ALL run-scoped stages PASS (observer runs
064509Z/074459Z). The in-flight grading pair fix is
rhels/lab-agentops PR #70,
still OPEN (not merged/fixed): V-E2E-01..05 PASS, V-E2E-06 NOT-RUN.
The 06:32Z cycle was bracketed, not overlapped, by observer runs; a
one-shot observation is scheduled for the 2026-11-01 12:32Z cycle.
rhels/lab-agentops#28
remains OPEN; V-AD-01/02/03 unposted for the latest cycle.
CRC-A7 — Recovery is a drill, and the drill is timed (DR) [CLI]
- Persona: Platform admin. Goal: the cluster’s disaster recovery is a proven procedure, not a hope.
- Preconditions: an owner-authorized drill window — this story runs on drill days, not per-run.
- Steps: execute
recover.sh(inrhels/local-k8s-gitops) end to end: preflight (incl. Vault unseal via the sanctioned path), snapshot, delete, start, bootstrap, convergence, acceptance battery. - Expected: the full recovery completes at the proven scale — baseline ~95 minutes was drilled down to 27m24s (Drill 3, 2026-10-25) — with the acceptance battery green (source: disaster-recovery.md, the DR chapter’s CRC section; recover.sh record).
- Assert: drill wall-clock recorded as the measured
value (regression = materially above the 27–30m band);
acceptance battery exit
0; the drill report is filed with the run’s records.
User stories
CRC-U1 — oc login as a directory user [CLI]
- Persona:
dev1. - Steps:
oc loginagainst the cluster API via theagentops-ldapprovider (from the m4 — the recorded working path). - Expected: login succeeds as dev1 with dev1’s groups
(the CRC-A3 projection made visible)
(source: lab record — “
oc loginas dev1 works”). - Assert:
oc whoami→dev1;oc groupscontains dev1’s projected groups.
CRC-U2 — Work inside my own namespace [CLI]
- Persona:
dev1, in an MCP-created app1001 namespace (MCP-U1’s product). - Steps: deploy the dummy workload; read it back.
- Expected: the workload runs; the namespace carries the
BSN labels, the ResourceQuota from the request, and the
app1001-nonprodRoleBinding with admin (non-prod) (source: namespace-service.md, step 8). - Assert: pod phase ==
Running; quota hard values == the request file’s; RoleBinding roleRef name ==admin.
CRC-U3 — Other BSNs’ namespaces are closed (negative) [CLI]
- Persona:
dev1reaching for another segment’s namespace. - Steps: attempt to read/patch resources in a namespace belonging to a BSN whose groups dev1 is not in.
- Expected: refused by RBAC; production bindings, where they exist for dev1’s own groups, are view — never admin (source: namespace-service.md — “admin in non-production, view in production”).
- Assert:
oc auth can-i update deployments -n <foreign-ns>→no; for a prod namespace of dev1’s own BSN:can-i get pods→yes,can-i update→no.
Gaps
- Framing gap (by design): every story here is conditional on a running CRC; the suite must treat “stopped” as a first-class not-run state with the checklist as its source — the hourly suite’s infra-down grading is the existing mechanism.
- Manual-only: CRC-A7 (drills are owner-authorized, destructive-by-design events) and CRC-A2’s htpasswd leg (break-glass credentials are exercised sparingly, on the admin’s word). Both are deliberately manual; everything else codes.
- TBD: no documented expectation for CRC’s own resource headroom (the m4’s CRC sizing — 8 CPU / 18 GiB — is a record, not a threshold with an alert behind it).