Modeling and API Simulation
Topograph models are YAML files used to simulate discovered topology without querying a real cloud API, NetQ instance, InfiniBand fabric, or Kubernetes cluster. They are primarily used by tests and local development, but they are also useful when validating a scheduler integration against known topology shapes.
A model describes the same canonical topology that real providers eventually produce:
- A variable-depth switch tree, used for Slurm
topology/treeoutput and Kubernetesfabric.topograph.run/tier-Nlabels - Node membership in an accelerator domain and optional sub-domain, used for block topology and the
accelerator.topograph.run/domainandaccelerator.topograph.run/sub-domainlabels - Optional per-node labels and provider-specific annotations used by provider simulations
Model loading lives in pkg/models. Model fixtures live under tests/models/.
Where Models Are Used
Models are consumed in several simulation and local-development flows.
KWOK Clusters
kwok-nodes renders virtual Kubernetes Node objects from a model file as a plain YAML manifest. The helper script scripts/create-kind-kwok-cluster.sh then creates or reuses a local kind cluster, installs KWOK into it, and applies that manifest. This is useful when you want to run Topograph against a Kubernetes API without provisioning real nodes.
Prerequisites:
kindinstalled and available onPATHkubectlinstalled and available onPATH- A Docker-compatible runtime supported by kind
- Network access to GitHub releases when installing KWOK manifests
Build the manifest renderer:
Render a KWOK node manifest from one of the embedded model fixtures:
Create or reuse a kind cluster named topograph, install KWOK, and apply the generated nodes:
Create or reuse a named kind cluster from an explicit model path, and keep the generated manifest:
To pass a kind cluster configuration file, add --kind-config path/to/kind.yaml. To pin KWOK installation to a release, add --kwok-release vX.Y.Z; otherwise the script uses GitHub’s latest KWOK release download URL.
The utility uses the model-derived instance-to-hostname mapping, so model hostname 1101 becomes Kubernetes node 1101 with:
topograph.run/instance: i-1101topograph.run/region: <derived-region-or-none>kwok.x-k8s.io/node=fakeas both a label and annotation- Model-derived labels such as
topology.kubernetes.io/regionandtopology.kubernetes.io/zone - Model-derived annotations such as
accelerator.topology.test/domain
Generated Kubernetes node names come from model hostnames and are normalized to valid lowercase DNS names. For example, model hostname I21 becomes Kubernetes node i21, while its generated instance ID i-I21 is stored in topograph.run/instance.
The script applies the manifest with kubeconfig context kind-<cluster>, matching the context name created by kind create cluster --name=<cluster>.
Test Provider
The test provider simulates the Topograph API lifecycle itself. It can return successful topology output, delayed completion, malformed-request failures, provider failures, or a request that remains pending.
Use it when testing clients that call:
POST /v1/generateGET /v1/topology?uid=<request-id>
For the complete API status-code simulation behavior, see Test Mode and Test Provider.
Provider Simulations
Several providers also have simulation variants, such as:
aws-simgcp-simoci-simnebius-simnscale-simlambdai-simdsx-sim
These providers load a model file and then simulate that provider’s API responses. This is useful when you want to exercise the normal provider translation logic without real provider credentials or infrastructure.
Simulation providers share these common parameters:
Example request:
Model File Shape
A model usually has one required top-level section and one optional topology section:
switches is a map and blocks is a list. blocks[].nodes is where model files declare compute node names; it creates the node records, applies block labels and annotations, and optionally attaches those nodes to a leaf switch through blocks[].switch. switches may be omitted for block-only models.
Switches
The switches map describes the network hierarchy. Each key is the switch ID. Each value may contain:
Example:
Switch rules:
- A switch can have at most one parent switch.
- Empty leaf switches may be omitted from the
switchesmap. A child switch named in a parent’sswitcheslist is created automatically when it has no top-level definition. - A switch that defines labels, annotations, or child switches must have a top-level entry.
- If a block names a switch with
blocks[].switch, that block’snodesare attached to the switch before switch validation runs.
Blocks
The blocks list describes sets of compute instances with similar hardware and connectivity characteristics. Each entry may contain:
Example:
Block rules:
- The
blockssection is the only place model files declare compute node names. - Each block entry must declare at least one node.
switchis optional. When set, it must reference a switch declared at the top level or named as a child in the switch hierarchy.blocks[].nodescreates node entries automatically.
Compact Ranges
Model node lists support compact ranges:
These expand to:
Ranges are accepted in:
blocks[].nodes
Derived Data
After YAML parsing, Topograph completes the model before simulation uses it:
- Compact ranges in Capacity block node ranges are expanded.
- Block
switchreferences attach block nodes to switches. - Switch names are copied from their map keys.
- Nodes are created from
blocks[].nodes. - Node
NetLayersis derived from the switch path from leaf to root. - Node labels are built by merging labels from the switch path and block labels.
- Node annotations are built by merging annotations from the switch path and block annotations.
Instancesis derived from node names and grouped bylabels.topology.kubernetes.io/region; nodes without a region usenone.
These derived fields are not written in YAML.
Complete Examples
Blocks With Switches
This model creates nodes from block membership and attaches them to a leaf switch.
After loading:
n1,n2, andn3are hostnames mapped from instance IDsi-n1,i-n2, andi-n3n1andn2belong to the first block and have theaccelerator.topology.test/domain: nvl1annotationn3belongs to the second block and has theaccelerator.topology.test/domain: nvl2annotation- All three nodes have network layers
[leaf, core]
Blocks Without Switches
This model omits switches. Nodes are still created, block metadata is still applied, and generated instances have no network layers.
After loading:
n1andn2belong to the first blockn1andn2have theaccelerator.topology.test/domain: nvl1annotationn1andn2have no network layers
Simulating the API
To simulate the Topograph API lifecycle, configure the test provider:
Then submit a request that names a model:
Expected flow:
POST /v1/generatereturns202 Acceptedand a request ID.GET /v1/topology?uid=<request-id>returns202 Acceptedwhile the request is queued or processing.- When processing completes,
/v1/topologyreturns200 OKwith the selected engine output.
To simulate API failures, set generateResponseCode, topologyResponseCode, and errorMessage in provider.params. For example:
Choosing the Right Simulation Path
Use the test provider when you want to validate API-client behavior:
- Request IDs
- Polling
- Pending responses
- Error status codes
- Retry behavior
Use a *-sim provider when you want to validate provider-specific topology translation:
- AWS, GCP, OCI, Nebius, Nscale, Lambda AI, or DSX topology paths
- Pagination behavior in simulated provider APIs
- Engine output generated from provider-shaped data
- Tree and block topology output from the same model
Validation Checklist
Before using a new model in a regression test:
- Confirm every switch child has only one parent.
- Confirm every block
switchreference points at an existing switch. - Confirm no node appears under two blocks.
- Run the relevant provider simulation test or API flow with the target engine.