This guide walks through every file you need to touch to add full support for a new network OS. Follow the steps in order — each step depends on the previous ones.
There are three patterns in this codebase. Pick the one that matches the config format:
| Config format | Pattern | Example |
|---|---|---|
| IOS-style indented text | Extend IOSParser |
EOS, NX-OS |
| Non-IOS indented text (brace/hierarchical) | Extend BaseParser, write custom tokenizer |
JunOS |
| XML document | Extend BaseParser, use xml.etree.ElementTree |
PAN-OS |
If the syntax is close enough to IOS that 80%+ of parse_* methods work unchanged, extend IOSParser and only override the methods that differ (see EOSParser). Otherwise extend BaseParser directly.
File: confgraph/models/base.py
Add a value to the OSType enum:
class OSType(str, Enum):
...
MYOS = "myos"
File: confgraph/parsers/myos_parser.py
Extend BaseParser (or IOSParser). You must implement these four abstract methods at minimum — the rest have default stubs that return empty lists:
from confgraph.parsers.base import BaseParser
from confgraph.models.base import OSType
class MyOSParser(BaseParser):
def __init__(self, config_text: str) -> None:
super().__init__(config_text, OSType.MYOS, syntax="ios")
def parse_vrfs(self) -> list[VRFConfig]: ...
def parse_interfaces(self) -> list[InterfaceConfig]: ...
def parse_bgp(self) -> list[BGPConfig]: ...
def parse_ospf(self) -> list[OSPFConfig]: ...
def parse_route_maps(self) -> list[RouteMapConfig]: ...
def parse_prefix_lists(self) -> list[PrefixListConfig]: ...
All parse_* methods are wired into BaseParser.parse() automatically via _PARSE_STEPS. You do not need to call them yourself.
If using CiscoConfParse (IOS-style), call self._get_parse_obj() to get the lazy-loaded parse object.
If NOT using CiscoConfParse (XML, custom tokenizer), override:
_extract_hostname() — return hostname from your format_collect_unrecognized_blocks() — return []File: confgraph/parsers/__init__.py
from confgraph.parsers.myos_parser import MyOSParser
__all__ = [..., "MyOSParser"]
File: confgraph/cli.py
Two changes:
# 1. Add alias mapping
_OS_ALIAS = {..., "myos": "myos"}
# 2. Add detection heuristic
def _detect_os(text: str) -> OSType:
for sig in ("MyOS-specific-string",):
if sig in text:
return OSType.MYOS
...
# 3. Add dispatch
if detected == OSType.MYOS:
from confgraph.parsers.myos_parser import MyOSParser
parsed = MyOSParser(text).parse()
# 4. Add to --os option choices
@click.option("--os", type=click.Choice([..., "myos"]))
File: confgraph/graph/builder.py
If your OS introduces new node types (e.g., PAN-OS added zone), add entries to NODE_STYLE and NODE_LABEL_PREFIX, and add a node-creation block in _add_defined_nodes().
If your OS reuses existing node types (interfaces, bgp_instance, etc.), no changes needed here.
File: confgraph/analysis/dependency_resolver.py
If your OS introduces new cross-reference relationships (e.g., zone → interface), add a _resolve_myos_thing() method and call it from resolve():
def resolve(self) -> DependencyReport:
links = [...]
links.extend(self._resolve_myos_thing())
...
def _resolve_myos_thing(self) -> list[DependencyLink]:
links = []
for zone in self._config.zones:
for iface in zone.interfaces:
links.append(self._link("zone", zone.name, "interface", "interface", iface))
return links
File: confgraph/graph/exporters/html.py
If your OS adds new node types that should appear as sidebar clusters, add an entry to CLUSTER_DEFS and to the LARGE_TYPES set and layout roots arrays:
const CLUSTER_DEFS = [
...
{ id: 'mytype', label: 'My Type', rootType: 'mytype', color: '#...' },
];
File: samples/myos_sample.<ext>
Create a realistic sample that exercises all implemented parse methods. Then generate its HTML:
uv run confgraph map samples/myos_sample.cfg --os myos --output-dir samples/
Verify with:
uv run confgraph info samples/myos_sample.cfg --os myos
uv run confgraph map samples/myos_sample.cfg --os myos --lint
Create docs/MYOS_PARSER_SUPPORT.md following the structure of any existing OS doc (e.g., PANOS_PARSER_SUPPORT.md):
confgraph info outputThen add a row to PARSER_SUPPORT_MATRIX.md and update README.md.
[ ] models/base.py — OSType enum value
[ ] parsers/myos_parser.py — Parser class implementing parse_* methods
[ ] parsers/__init__.py — Export MyOSParser
[ ] cli.py — Alias, detection, dispatch, --os choice
[ ] graph/builder.py — Node styles + _add_defined_nodes (if new node types)
[ ] analysis/dependency_resolver.py — New edge resolvers (if new relationships)
[ ] graph/exporters/html.py — CLUSTER_DEFS (if new sidebar clusters)
[ ] samples/ — Sample config + generated HTML
[ ] docs/MYOS_PARSER_SUPPORT.md
[ ] docs/PARSER_SUPPORT_MATRIX.md
[ ] README.md