This template rendering system provides a flexible, inheritance-based approach to generating network device configurations. It queries structured data from Nautobot (a network source of truth) and renders device configurations using Jinja2 templates with custom filters.
Renderer: Main orchestration class that:
Filters: Python functions that transform data within templates
filters/ modules (bgp, device, ip, isis, location, vault)Templates: Jinja2 templates organized by platform, role, and version
Dataclasses: Structured Python objects for type-safe data handling
Interface: Network interface representationBGPPeer: BGP peering informationVRF: Virtual routing and forwarding instanceConnectedDevice: Details about connected neighborsTemplates are organized in a hierarchical directory structure:
The renderer determines which entrypoint templates to use based on device attributes:
cumulus-linux)tan-leaf)intended-firmware.versionExample Path: cumulus-linux/tan-leaf/5.6.0/entrypoint/startup.yaml.j2
template-cli is a local template development command, not a command exposed by a running Config Manager deployment or by the installer on the target host. It is installed into any Python environment that installs the nv-config-manager-templates package; from the Config Manager source tree, run it with uv run template-cli from components/network-templates.
Use template-cli to iterate on built-in templates or external template plugins before packaging them for the render service. Deployed environments use the same render engine through the Config Manager UI, render API, event consumers, and staged template plugin content.
Common commands:
Without --vault, encrypted fields in CLI output are placeholders. Use --vault before copying rendered configs to lab hardware. For render regression tests, add expected files under tests/resources/expected_config/ and matching Nautobot JSON under tests/resources/nautobot/, then run uv run pytest (see the nv-config-manager-templates README).
The system uses Jinja2’s template inheritance to enable code reuse and maintainability.
Level 1: cumulus-linux/role_common/base/startup.yaml.j2
This defines the overall structure with named blocks. The required keyword ensures child templates must implement these blocks.
Level 2: cumulus-linux/tan-leaf/base/startup.yaml.j2
This implements role-specific blocks by including role-specific templates.
Level 3: cumulus-linux/tan-leaf/5.6.0/entrypoint/startup.yaml.j2
This simply extends the role base. If version 5.6.0 needs specific changes, blocks can be overridden here.
Include templates can also inherit from each other:
Common Interface Template: cumulus-linux/role_common/include/interface.j2
Role-Specific Interface Template: cumulus-linux/tan-leaf/include/interface.j2
This inherits management and loopback blocks from common, only implementing swp-specific logic.
Filters are the primary mechanism for extracting and transforming Nautobot data within templates. All filters are pure Python functions that take data as input and return processed output.
Filters are organized into modules by functionality:
Extract device attributes from Nautobot GraphQL data.
Example Usage:
Example Usage:
Interface Object Properties:
Example Usage:
Transform BGP ASN formats.
Example:
Network calculations and IP address manipulations.
Example Usage:
IS-IS protocol helpers.
Example:
Extract site/location-level data (operates on location_data, not device_data).
Example Usage:
Secret management and encryption (for passwords, keys, and so on).
Secret Loading Modes:
{path}:{key}) when NV_CONFIG_MANAGER_SKIP_VAULT=1Example Usage:
The system queries Nautobot using GraphQL to retrieve comprehensive device and location data.
The device query (query_config_data_by_device_id_v2.graphql) retrieves:
The location query (query_location_data.graphql) retrieves site-level data:
The config_context field contains custom JSON data defined in Nautobot:
Allowed password-mapping roles are admin, ro, and rw.
Based on your device, identify:
cumulus-linux, arista-eos, mlnx-os, nv-ostan-leaf, smn-spine, wan, oob-switch, and so on5.6.0, 4.29.3MIf creating a new role, start with a base template:
File: {platform}/{role}/base/{config-file}.j2
Implement specific configuration sections:
File: {platform}/{role}/include/interface.j2
File: {platform}/{role}/{version}/entrypoint/{config-file}.j2
Ensure the device in Nautobot has:
intended-firmware.version matching your template pathCache device data:
Render locally:
Add expected output: save the rendered output to tests/resources/expected_config/my-device_startup.yaml (naming convention is {hostname}_{entrypoint}).
Run tests: uv run pytest tests/nv_config_manager_templates/test_render.py.
Use Inheritance: Do not duplicate configuration. Extend base templates and override only what differs.
Keep Includes Focused: Each include template should handle one logical section (interfaces, routing, QoS, and so on).
Fail Explicitly: Use filters with fail_if_missing=True (default) to catch data issues early.
Handle Optional Data: Check for None before using optional fields:
Use Filters for Logic: Move complex logic into filters rather than templates:
Whitespace Management: Jinja2 trim_blocks=True is enabled. Use {%- and -%} for additional control:
Single Responsibility: Each filter should do one thing well.
Type Hints: Use type hints for clarity:
Error Handling: Raise FilterException with clear messages:
Test Coverage: Every filter must have unit tests:
Immutable Data: Use frozen=True dataclasses to prevent accidental mutations.
Consistent Naming: Follow consistent naming conventions for devices, interfaces, VLANs, and so on.
Config Context: Use config context for:
Interface Roles: Define and use interface roles consistently (Uplink, Downlink, Management, and so on)
Tags: Use tags for:
enable-feature-x)production, staging)IP Hierarchy: Maintain proper prefix parent-child relationships:
Version-Specific Changes Only: Only create version-specific templates when absolutely necessary.
Feature Detection: When possible, use tags rather than version checks:
Deprecation Path: When deprecating old versions, keep templates for graceful migration.
Template: my-platform/my-role/include/interface.j2
Template: my-platform/my-role/include/bgp.j2
Template: my-platform/my-role/include/features.j2
Template: cumulus-linux/cin-leaf/base/dhcpd.conf.j2
Template: my-platform/my-role/include/bgp-vrf.j2
Template: my-platform/my-role/include/management.j2
Template: my-platform/my-role/include/interface-advanced.j2
This template rendering system provides a powerful, maintainable approach to network configuration management. By leveraging:
You can build scalable configuration templates that adapt to diverse network environments while maintaining consistency and reliability.
For support or questions about template development, contact the CFA team or the nv-config-manager-templates README.