Two-Node Toolbox (TNT) is a deployment automation framework for two-node OpenShift clusters in development and testing environments. It supports arbiter and fencing topologies via dev-scripts, kcli, and assisted installer deployment methods. Contributions from across Red Hat engineering are welcome.
-
Fork
openshift-eng/two-node-toolboxon GitHub. -
Clone your fork:
git clone git@github.com:<your-username>/two-node-toolbox.git cd two-node-toolbox
-
Set up commit signing (GPG or SSH). The repo enforces signature verification — unsigned commits are rejected. See GitHub's signing docs for setup instructions.
-
Ensure a container engine is available. All linters run in containers, so no local tool installation is needed beyond the engine itself.
CONTAINER_ENGINEdefaults topodman; override withCONTAINER_ENGINE=dockerif needed. -
Install the pre-commit hook:
make install-pre-commit
The hook runs
make verifyautomatically on every commit, catching lint issues before they reach CI.
| Type | Location | Guidance |
|---|---|---|
| New deployment method | deploy/openshift-clusters/roles/ |
Add an Ansible role, wire into the Makefile |
| New topology | deploy/openshift-clusters/ |
Add config template and playbook support |
| Bug fix / enhancement | Relevant component directory | Follow existing patterns in that area |
| Helper script | helpers/ |
Standalone utility for cluster operations |
| Documentation | docs/, component READMEs |
See the Documentation section |
| CI / Prow job | External: openshift/release repo |
CI configuration lives outside this repo |
Create a branch from main using the appropriate naming convention:
- Features:
OCPEDGE-XXXX-short-slug - Bug fixes:
fix/OCPBUGS-XXXX-slug
Run all checks before committing:
make verifyFor targeted checks, run individual linters:
make shellcheck # Shell script linting
make yamlfmt # YAML formatting (auto-formats by default)
make ansible-lint # Ansible linting + playbook syntax checkmake yamlfmt auto-formats files by default. make verify runs it in
validate-only mode (no modifications). make shellcheck is read-only.
All linters run inside containers via hack/ scripts — no local tool
installation is required beyond a container engine.
#!/usr/bin/bashshebangset -euo pipefailat the top- Quote all variables to prevent word splitting
- UPPER_CASE for variable names
- Must pass shellcheck
- 2-space indentation
- Quote strings containing special characters
- Must pass yamlfmt
- Follow existing role patterns in
deploy/openshift-clusters/roles/ - Must pass ansible-lint (
.ansible-lintdefines the baseline) - Do not add new entries to the
.ansible-lintskip list — fix violations instead - Playbooks must pass
ansible-playbook --syntax-check(run automatically bymake ansible-lint)
- PEP 8 compliance, must pass ruff (checked by CodeRabbit on PRs)
- Use f-strings for formatting
- Local:
make verifyruns all linters (shellcheck, yamlfmt, ansible-lint). - Pre-commit: The hook runs
make verifyautomatically on every commit. - End-to-end: Deployment changes require testing on an actual cluster (AWS hypervisor or Bring Your Own Server). Not everything in deployment automation is unit-testable — integration testing against real infrastructure is expected.
- CI: Prow jobs and CodeRabbit run on PRs. Both must pass before requesting human review.
- Never hardcode credentials, tokens, or secrets in code or commits.
- Use environment variables for sensitive data (
CI_TOKEN, pull secrets). - Pull secrets belong in
config/pull-secret.json(gitignored). - Verify that logs and command output do not leak credentials before committing.
.gitignorealready excludes sensitive config files — do not circumvent it.
- Update relevant READMEs when changing behavior.
- Professional, terse, customer-centric style — no emojis or marketing language.
- When adding new Make targets, update the Makefile help text.
- CLAUDE.md maintenance: If a change adds new paths, commands, roles,
or configuration options, update
CLAUDE.mdat the repo root. AI-assisted contributors rely on it for accurate context. Treat it like any other documentation — it must reflect the current state of the repo.
- With Jira ticket:
OCPEDGE-XXXX: description(primary format) - Without ticket:
type: descriptionwhere type is one of: feat, fix, docs, chore - All commits must be signed (GPG or SSH). The repo has signature verification enabled — unsigned commits are rejected.
- Keep commits focused and atomic.
- Open PRs from your fork against
main. - PR title follows the same convention as commit messages.
- CodeRabbit runs automated review on all PRs.
- Prow jobs run additional CI checks.
- Review is handled by teams in OWNERS: edge-enablement and team-dragonfly.
- Address CodeRabbit feedback before requesting human review.
- Run
make verifylocally before pushing.