This guide explains how to contribute the offline test data redfish_ctl runs against: captured
Redfish resources that let the pytest mock service in tests/conftest.py serve real-shaped responses
for any vendor — Dell iDRAC, Supermicro, HPE iLO, or generic DMTF Redfish — with no hardware in the
loop. It is written for anyone adding coverage, not just the maintainers.
Default rule: never capture from production, or from hardware you are not authorized to read. Use an approved lab BMC and a short-lived read-only account, sanitize every file before it enters the repo, and prove the data with the offline suite before committing.
Pick the path that matches what you are contributing — the two are deliberately separate:
- Path A — a full BMC crawl. Capture the entire Redfish tree with
redfish_ctlitself and commit it as a vendor corpus. Best when adding a new vendor or model; one capture then backs many later commands with only a thin behavioral test. This is how the Supermicro GB300 and X10 corpora were contributed. - Path B — a curated fixture set. Hand-pick, sanitize, and import only the handful of resources one specific test needs. Best when adding or fixing one command on an already-covered vendor.
For the existing shared archive, see the Redfish Corpus Library, the repository index for committed corpus tarballs and pull-all extraction commands.
redfish_ctl can capture its own test data. The discovery command does a deep crawl of a BMC and
writes one JSON file per Redfish URI under ~/.json_responses/<ip>/, plus rest_api_map.npy for
the legacy URL/method map and rest_api_map.status.json, the JSON status/error sidecar written by
Discovery.save_url_file_mapping. This is exactly the layout the committed corpora pack (the
filtered tests/supermicro_gb300_corpus.tar.gz LFS tarball, or overlay sets like
tests/supermicro_x10_fixtures/). To contribute coverage for a BMC this project has not seen:
-
Crawl an approved lab BMC (read-only; never production, never someone else's hardware):
export REDFISH_IP=<approved-lab-bmc> export REDFISH_USERNAME=<short-lived-readonly-account> export REDFISH_PASSWORD=<password> # keep out of shell history redfish_ctl discovery # writes ~/.json_responses/<ip>/
-
Sanitize the tree — this is mandatory (a full crawl carries identifiers). Run the bundled redactor, which replaces the source management IP with an RFC 5737 documentation address, renames the
<ip>directory, and scrubs identifier fields (serial/service tag, asset tag, UUID, MAC, hostname). It writes a clean copy straight into a corpus directory matching the existing convention (tests/<vendor>_<model>_corpus/json_responses/<placeholder-ip>/):python tools/redact_corpus.py ~/.json_responses/<ip> \ --out tests/<vendor>_<model>_corpus/json_responses
It reports only counts (never values) and skips
.npymaps (regenerate those from the redacted tree or leave them out). Treat it as a first pass, not a guarantee: then apply the Redact Before Import rules by hand for anything vendor-specific, run that section's secret scan over the output, and read the files yourself before committing. -
Add a thin corpus-backed test (see
tests/test_supermicro_gb300_corpus.pyandtests/test_supermicro_x10_fixtures.py) that loads the corpus and asserts a command's contract against it — URL/payload for mutations,CommandResultshape for reads — with no live BMC. -
Binaries go to Git LFS automatically —
.gitattributesalready routes*.npy,*.zip,*.exe, and firmware trees to LFS; the Redfish JSON stays as plain committed text. -
Gate before committing — the offline suite must stay green with the live variables cleared:
env -u REDFISH_IP -u REDFISH_USERNAME -u REDFISH_PASSWORD \ pytest -q
Use this path to add or fix a single command on a vendor the suite already covers. You hand-pick,
sanitize, and import only the resources that test needs. The commands and file examples below use a
Dell iDRAC for concreteness, but the same steps apply to any vendor — capture from the approved lab
BMC, redact, and import under that vendor's fixture directory (tests/idrac_fixtures/,
tests/supermicro_fixtures/, tests/hpe_fixtures/, tests/generic_fixtures/, …).
Redfish-Mockup-Creator, the DMTF tool from DMTF/Redfish-Mockup-Creator, creates a file tree from a live Redfish service.tools/redfish_validate.py, the repository schema helper, validates standard Redfish surfaces against cached DMTF schemas.tests/idrac_fixtures/, the Dell overlay directory loaded bytests/conftest.py, holds hand-curated fixture JSON for missing Dell paths.redfish_ctl/json_responses/, the captured DMTF mockup base tree used by the default mock service, stays generic and should not receive Dell-only overlays.
No API key is required. A capture needs only an approved lab BMC address and a temporary BMC account with read-only permission for the resources being captured. Never paste credentials into chat, docs, commit messages, logs, or test output.
Run the capture from a trusted local shell. REDFISH_IP, the endpoint variable read
by this project and its tests, should point at an approved lab iDRAC. Use a
short-lived lab credential. The DMTF creator requires the password as a command
argument, so avoid shared hosts and do not preserve the command in shell history.
git clone https://github.com/DMTF/Redfish-Mockup-Creator.git \
/tmp/Redfish-Mockup-Creator
cd /tmp/Redfish-Mockup-Creator
python3 -m venv /tmp/redfish-mockup-creator-venv
. /tmp/redfish-mockup-creator-venv/bin/activate
python -m pip install -r requirements.txt
printf 'iDRAC IP or host: '
read -r REDFISH_IP
printf 'iDRAC username: '
read -r REDFISH_USERNAME
read -rsp "iDRAC password: " REDFISH_PASSWORD
printf '\n'
python redfishMockupCreate.py \
--user "$REDFISH_USERNAME" \
--password "$REDFISH_PASSWORD" \
--rhost "$REDFISH_IP" \
--Secure \
--Auth Session \
--Dir /tmp/idrac-redfish-mockup--Dir, the Mockup Creator output option, writes one directory per Redfish URI.
The creator stores JSON resources as index.json files under that tree. Keep the
raw output outside the repository until redaction and validation are complete.
Do not pass --Headers unless the current task explicitly needs headers and
you have a redaction plan for auth tokens, cookies, and request IDs.
Import only the paths needed by the test package. For an S1 test, that usually means one collection and one or two leaves, not a full BMC crawl.
Example mapping:
/redfish/v1/Systems/System.Embedded.1/Bios
-> tests/idrac_fixtures/_redfish_v1_Systems_System.Embedded.1_Bios.json
/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/DellJobService
-> tests/idrac_fixtures/_redfish_v1_Managers_iDRAC.Embedded.1_Oem_Dell_DellJobService.json
The fixture filename is the Redfish path with slashes replaced by underscores
and a .json suffix. Do not include query strings in filenames. If a test needs
an expanded resource, store the expanded shape only when the command actually
depends on the expanded fields.
Review every selected JSON file before it enters tests/idrac_fixtures/.
Remove or replace:
- BMC passwords, session tokens, cookies, auth headers, and API keys.
- Service tags, serial numbers, asset tags, UUIDs, WWNs, and license keys.
- MAC addresses, private IP addresses, DNS names, rack names, and user names.
- Certificate private material and raw auth responses.
- Any
Headerscapture that includesX-Auth-Token,Set-Cookie, or similar secret-class values.
Prefer stable placeholders that keep shape but do not identify hardware:
{
"SerialNumber": "REDACTED",
"AssetTag": "REDACTED",
"IPv4Addresses": []
}Run a quick secret scan over the candidate files:
secret_pattern='password|passwd|token|secret|set-cookie|x-auth|session'
secret_pattern="${secret_pattern}|serial|servicetag|asset|license|wwn"
secret_pattern="${secret_pattern}|[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}"
rg -n "$secret_pattern" /tmp/fixture-candidatesA bare Password-is-null check is not enough: vendor OEM attribute maps store
credentials under dotted attribute keys the generic pattern misses. On Dell the
DellAttributes file (_redfish_v1_Managers_*_Oem_Dell_DellAttributes_*.json)
carries live Users.<n>.SHA256Password, Users.<n>.SHA256PasswordSalt,
Users.<n>.IPMIKey, Users.<n>.MD5v3Key, and SNMP IPMILan.1.CommunityName /
SNMP.1.AgentCommunity values. tools/redact_corpus.py catches these by matching
the last dotted segment against its credential-suffix set, and
tests/test_corpus_no_secrets.py fails the build if any committed corpus still
carries a non-empty credential value — run both before adding a capture:
rg -n 'SHA256Password|SHA256PasswordSalt|IPMIKey|MD5v3Key|CommunityName|AgentCommunity' \
/tmp/fixture-candidatesThis scan is only a guardrail. Read the files yourself before committing them.
First prove the JSON parses:
python -m json.tool \
tests/idrac_fixtures/_redfish_v1_Systems_System.Embedded.1_Bios.json \
>/dev/nullThen validate standard Redfish resources with tools/redfish_validate.py.
REDFISH_SCHEMA_OFFLINE, the environment variable read by that helper, prevents
network fetches and requires schemas already cached under tools/redfish-schemas/.
REDFISH_SCHEMA_OFFLINE=1 \
python tools/redfish_validate.py tests/idrac_fixturesThe validator classifies each JSON file as valid, error, or skipped. Use
--json when a script needs the same result as machine-readable output. OEM
resources often skip validation because no standard DMTF schema exists for their
private type. That is acceptable when the test asserts the exact command behavior
that depends on the OEM fields.
Copy only the redacted candidate files into tests/idrac_fixtures/. Do not copy
the whole Mockup Creator tree into the Dell overlay. If the full raw capture is
needed for later analysis, keep it outside the repository or in an approved
private artifact store.
After import, add or update a focused dual-mode test under tests/test_*_dualmode.py.
The test should assert the command contract:
- URL path or action target used by the command.
- POST or PATCH payload for mutating commands.
CommandResultshape and key fields for read-only commands.- No live BMC dependency when canonical
REDFISH_IPis unset.
Before committing, run the exact offline gate from a shell with the live variables cleared:
env -u REDFISH_IP -u REDFISH_USERNAME -u REDFISH_PASSWORD \
pytest -q
ruff check \
tests/test_<package>_dualmode.py
python -m json.tool \
tests/idrac_fixtures/<changed-fixture>.json \
>/dev/nullFor docs-only changes to this SOP, run:
env -u REDFISH_IP -u REDFISH_USERNAME -u REDFISH_PASSWORD \
pytest -q
ruff check docs/external/fixture-capture.mdIf the offline suite needs a live BMC, the fixture is not ready. Stop and record:
BLOCKER: fixture still depends on live iDRAC behavior
Observation: <missing path, missing field, or failing test>
Safe next step: capture and redact the smallest missing Redfish resource