Code generation
How the generated endpoint headers are produced and how to add an endpoint.
Code generation
include/forti_api/gen/** is generated and checked in, so users never need the generator. Its
inputs are:
codegen/api.toml: which FortiOS paths are generated and their C++ names (namespace, type and endpoint alias overrides).codegen/schema/<version>/cmdb/<path>.json: schema snapshots the FortiGate itself returns forGET /api/v2/cmdb/<path>?action=schema.
The tool is tools/fortios/fortios.py (Python 3.12, standard library only):
1tools/fortios/fortios.py --env-file .env pull [PATH...] # refresh snapshots from a device (GET only)2tools/fortios/fortios.py --env-file .env crawl # discover cmdb paths via datasource references3tools/fortios/fortios.py gen # regenerate the headers4tools/fortios/fortios.py check # fail if the headers are out of date (CI)
Generation is deterministic: the same manifest and snapshots always produce byte-identical headers.
Discovery
The catalogs in codegen/catalog/<version>/ record what a device offers; they contain paths and
schema metadata only, never device data:
cmdb.json(fortios.py crawl): every configuration path, found fromcodegen/seeds.txt, the cmdb paths the web GUI references, and thedatasourcereferences inside each schema, with its category, key and attribute count. Every entry was confirmed by the device answering?action=schema.gui-api.json(fortios.py mine): the monitor, log and service paths the device's web GUI calls, extracted statically from its JavaScript bundle (and the HTTP method where the call site shows it). Only path strings are kept.
Both are read-only against the device and converge: running them again finds nothing new.
Adding an endpoint
- Add a
[[cmdb]]entry tocodegen/api.toml(path, andnamespace,type,aliaswhen the defaults do not read well). fortios.py pull <path>to fetch its schema snapshot.fortios.py gen, then build and run the tests.
What the generator produces
- A struct per object with every attribute as
fortiapi::Field<T>, documented from the schema; nested objects as nested structs, table rows as...Entrystructs, name references asstd::vector<fortiapi::Ref>. - A static
visit()listing every attribute's FortiOS key, member, reset value and flags; the serialization infield.hppis driven by it. - A
...Specand aTableorSingletonalias. - Option constants in a namespace beside the type.
Behavior lives in hand-written headers: client.hpp (transport), field.hpp (field states and
serialization), endpoint.hpp (Table, Singleton), monitor.hpp, and the helper headers.