Student Readiness Skill
When to Use
- Developer asks "is my environment ready for students?"
- Pre-training or pre-demo readiness verification
- Multi-user environment provisioning validation
- Validating any AgnosticD-deployed environment for end-user consumption
- Comparing a deployed environment against expected workshop requirements
- Post-deployment smoke test before handing off to participants
Instructions
This skill defines a diagnostic process, not a tool wrapper. When activated, gather the required input from the user, determine the environment type, then execute the applicable checks using oc, curl, and/or ssh.
- Read
references/REFERENCE.mdwhen you need the list of complementary RHDP Skills Marketplace tools and their setup commands - Read
references/research-questions.mdwhen encountering a (RESEARCH NEEDED) marker
Gotchas
- The RHDP user format is
userN(e.g.user1), notuser-1orstudent1. Showroom terminals will fail silently if the format is wrong. - Do NOT create extra IdPs on the cluster — RHDP pre-provisions htpasswd users. Creating new IdPs breaks the existing user setup.
oc loginwith a student user may fail if the oauth pod is still rolling out — wait foroc get co authenticationto show Available=True before diagnosing login failures.- Route hostnames include the GUID — hardcoding hostnames in checks will fail for different deployments. Always derive routes dynamically with
oc get route. - AAP environments need both the AAP controller URL AND the student's AAP credentials, not just the OpenShift credentials.
- After
agd start(environment was previously stopped), prioritize checks in this order: #1 (cluster access — nodes must be Ready), then #4 (operators — all CSVs must be Succeeded). These degrade most during a stop cycle. Only proceed to checks #2 and #3 (Showroom, terminal) once the cluster and operators are healthy, as Showroom pods may fail to start if operators are not ready first.
Required Input
Before running checks, collect the following from the user:
| Input | Required | Example |
|---|---|---|
| OpenShift API URL | Yes (OCP) | https://api.cluster.example.com:6443 |
| Login token or credentials | Yes | sha256~abc... or username/password |
| Workshop GUID | Yes | abc123 |
| Expected environment type | Yes | OCP shared, OCP dedicated, RHEL VM, AAP, hybrid |
| Number of students | If multi-user | 25 |
| Bastion hostname | If RHEL VM or dedicated OCP | bastion.abc123.example.com |
| AAP controller URL | If AAP | https://controller.example.com |
Supported Environment Types
Adapt the checklist based on the environment type:
| Type | Description | Primary Access |
|---|---|---|
| OCP Shared Tenant | Students get scoped namespaces on a shared cluster | oc login with per-student credentials |
| OCP Dedicated | Students have cluster-admin, lab has a bastion VM | oc login + SSH to bastion |
| RHEL VM + Bastion | Bastion + node VMs, no OpenShift | SSH to bastion |
| AAP | Ansible Automation Platform controller + execution environments | AAP API + SSH |
| Hybrid | Combination (e.g., OCP cluster + bastion + AAP) | Multiple access methods |
Readiness Checklist
Run checks in order. Stop at the first failure and report it with the suggested fix.
1. Cluster / Host Access
OCP environments:
oc login --server=<API_URL> --token=<TOKEN> --insecure-skip-tls-verify
oc whoami
oc get nodes --no-headers | wc -l
- Verify: login succeeds, identity matches expected user/SA, nodes are Ready
RHEL VM environments:
ssh <user>@<bastion_host> whoami
ssh <user>@<bastion_host> uptime
- Verify: SSH succeeds, bastion is responsive
2. Showroom Accessibility (if deployed)
SHOWROOM_ROUTE=$(oc get route -n showroom-<GUID> -o jsonpath='{.items[0].spec.host}' 2>/dev/null)
curl -sI "https://${SHOWROOM_ROUTE}" | head -1
curl -s "https://${SHOWROOM_ROUTE}" | grep -c '<title>'
- Verify: route exists, HTTP 200, HTML content renders (not blank or error page)
3. Terminal Functionality (if deployed)
Pod-based terminal (type=showroom):
oc get pods -n showroom-<GUID> -l app=showroom-terminal --no-headers
- Verify: terminal pod is Running
Wetty terminal (type=wetty):
WETTY_ROUTE=$(oc get route -n showroom-<GUID> -l app=wetty -o jsonpath='{.items[0].spec.host}' 2>/dev/null)
curl -sI "https://${WETTY_ROUTE}/wetty" | head -1
- Verify: Wetty route exists and returns HTTP 200
4. Operators Ready (OCP environments)
oc get csv -A --no-headers | grep -v Succeeded
- Verify: all ClusterServiceVersions are in "Succeeded" phase (no failures or pending installs)
5. Namespaces and RBAC (OCP environments)
oc get namespaces | grep <expected_namespace_pattern>
oc auth can-i --list -n <student_namespace> --as=<student_user>
- Verify: expected namespaces exist, student users have expected permissions (create pods, get routes, etc.)
RHDP pre-provisioned clusters: User namespaces follow the userN format (no dash separator). The namespace pattern is <prefix>N (e.g., user1, user2), not <prefix>-N. When checking RBAC, use --as=user1 not --as=user-1. Detect the format by checking whether a keycloakrealmimport CR named sso exists in the keycloak namespace.
6. Workload Resources
oc get deployments -n <namespace> --no-headers
oc get pods -n <namespace> --no-headers | grep -v Running
oc get routes -n <namespace> --no-headers
- Verify: expected deployments exist, all pods are Running, routes resolve
7. Content-Environment Match
The values in Showroom's antora.yml attributes (e.g. openshift_cluster_ingress_domain) come from agnosticd_user_info module calls in the workload roles during provisioning — they are not hardcoded. This check verifies that the injected values match the actual deployed environment.
oc get ingresses.config/cluster -o jsonpath='{.spec.domain}'
- Verify: the
openshift_cluster_ingress_domainattribute in Showroom'santora.ymlmatches the actual cluster ingress domain
If they do not match, the diagnosis is one of:
- The workload role did not call
agnosticd_user_infowith the correct cluster URL key - The
antora.ymlin the content repo has a hardcoded value that overrides the injected attribute - The config was deployed against a different cluster than expected
(RESEARCH NEEDED — RQ-4)
8. AAP Readiness (if applicable)
curl -sk "https://<AAP_CONTROLLER>/api/v2/ping/"
curl -sk -H "Authorization: Bearer <TOKEN>" "https://<AAP_CONTROLLER>/api/v2/projects/" | python3 -c "import sys,json; print(json.load(sys.stdin)['count'])"
- Verify: controller API is reachable, expected projects/templates exist, execution environments are available
9. Multi-User Verification (if applicable)
The expected value of N is set by an AgnosticD multi-user variable in the config's vars file. When collecting the "Number of students" input (see Required Input), ask the developer what that variable is set to — that is the authoritative source, not the student sign-up count.
(RESEARCH NEEDED — RQ-7)
For N students, verify isolation:
for i in $(seq 1 $N); do
oc get namespace "student-${i}-<GUID>" --no-headers 2>/dev/null && echo "student-${i}: OK" || echo "student-${i}: MISSING"
done
- Verify: all N student environments are provisioned with correct namespace isolation
- If the count of OK namespaces is less than N, the provisioning loop did not complete — re-run
agd provisionor check the AgnosticD output logs for the failing iteration
RHDP pre-provisioned clusters: User verification works differently on clusters ordered from the RHDP catalog with "Create users on cluster" enabled:
# Detect RHDP user format by checking for Keycloak SSO realm
if oc get keycloakrealmimport sso -n keycloak &>/dev/null; then
# RHDP cluster — users are userN (no dash), managed by Keycloak
RHDP_USER_COUNT=$(oc get keycloakrealmimport sso -n keycloak \
-o jsonpath='{.spec.realm.users}' | python3 -c \
"import sys,json; print(len(json.load(sys.stdin)))")
echo "RHDP users detected: $RHDP_USER_COUNT (format: user1, user2, ...)"
for i in $(seq 1 $RHDP_USER_COUNT); do
oc auth can-i get pods -n "user${i}" --as="user${i}" 2>/dev/null \
&& echo "user${i}: OK" || echo "user${i}: MISSING/NO ACCESS"
done
fi
- Verify: OpenID identity provider is configured (not htpasswd) —
oc get oauth cluster -o jsonpath='{.spec.identityProviders[*].type}'should includeOpenID - Do NOT create additional identity providers; RHDP already configured OpenID via RHBK
- Each user has a unique password stored in the KeycloakRealmImport CR, not a shared password
Output Format
Present results as a pass/fail table:
Student Readiness Report — GUID: abc123
──────────────────────────────────────────────
# Check Status Notes
1 Cluster Access PASS 3 nodes Ready
2 Showroom Accessible PASS HTTP 200, content renders
3 Terminal Functional PASS Terminal pod Running
4 Operators Ready FAIL openshift-gitops CSV pending
5 Namespaces & RBAC PASS 25 student namespaces
6 Workload Resources PASS All pods Running
7 Content-Environment Match PASS Ingress domain matches
8 Multi-User Isolation PASS 25/25 environments ready
──────────────────────────────────────────────
Result: NOT READY — fix check #4 before proceeding
Escalation
When checks fail and the cause is not obvious:
- AgnosticD deployment failure -> See the agnosticd skill troubleshooting section
- Showroom rendering/terminal issue -> See the showroom skill troubleshooting section
- Infrastructure health -> Use
/health:deployment-validatorfrom the RHDP Skills Marketplace - Content quality -> Use
/showroom:verify-contentfrom the RHDP Skills Marketplace
Best Practices
- Run readiness checks after
agd provisioncompletes, before notifying students - For multi-user workshops, verify at least 3 student environments (first, middle, last)
- Save the readiness report output for post-training review
- If using the RHDP catalog, readiness checks should run after the catalog item's provisioning callback completes