Datasource Reference¶
The Operational Compliance app registers two Git datasource content types with Nautobot, allowing you to manage validation rules, rule groups, and command parser templates entirely from Git repositories. When a Git repository is synced, the app automatically creates or updates the corresponding database objects.
Datasource Content Types¶
| Content Type | Identifier | Purpose |
|---|---|---|
| Validation Rules | nautobot_operational_compliance.validation_rules |
Syncs validation rules, their command parsers (collectors), and rule groups from YAML files |
| Command Parsers | nautobot_operational_compliance.command_parsers |
Provides custom TextFSM and TTP parser templates for command output parsing |
To use either datasource, create a Git Repository in Nautobot (Extensibility > Git Repositories) and select the appropriate content type under Provided Contents.
Validation Rules Datasource¶
This datasource loads validation rules, their associated command parsers (called "collectors" in the YAML files), and validation rule groups from YAML files in a Git repository.
Directory Structure¶
The app supports two directory layout conventions. It checks for oc/ first, then falls back to operational-compliance/:
repository_root/
├── oc/ # or operational-compliance/
│ ├── rules/
│ │ ├── routing.yml # one or more YAML files
│ │ ├── interfaces.yml
│ │ └── system.yml
│ └── rule-groups/
│ ├── pre_change.yml
│ └── post_change.yml
- All
.ymland.yamlfiles in therules/directory (and subdirectories) are loaded recursively. - Files containing
samplein the filename are skipped. - The
rule-groups/directory is optional. If it does not exist, only rules are synced.
Validation Rules YAML Format¶
Each YAML file in the rules/ directory contains one or more rules as top-level keys. The key is a slug used to derive the display name if display_name is not provided.
---
# Key: rule slug (underscores become spaces, then title-cased for display_name)
bgp_neighbor_state:
display_name: "BGP Neighbor State" # optional, overrides slug-derived name
rule_type: "exact_match" # required: exact_match, tolerance, parameter_match, regex, or operator
description: "Verify BGP neighbor states" # optional
evaluate_args: # optional: kwargs passed to the jdiff comparison engine
tolerance: 5
collectors: # optional: list of command parsers to create
- name: "textfsm" # parser type: textfsm, napalm, ttp, or json
platform: "cisco_ios" # network_driver value of a Nautobot Platform
command: "show ip bgp summary" # CLI command to run on the device
jmespath: "[*].[$neighbor$, state_pfxrcd]" # JMESPath expression for data extraction
- name: "textfsm"
platform: "arista_eos"
command: "show ip bgp summary"
jmespath: "[*].[$bgp_neigh$, state_pfxrcd]"
Rule Fields¶
| YAML Field | Required | Model Field | Description |
|---|---|---|---|
display_name |
No | ValidationRule.name |
Human-readable name. Defaults to the slug with underscores replaced by spaces and title-cased. |
rule_type |
Yes | ValidationRule.rule_type |
One of: exact_match, tolerance, parameter_match, regex, operator |
description |
No | ValidationRule.description |
Free-text description of the rule |
evaluate_args |
No | ValidationRule.rule_options |
Dict of kwargs passed to jdiff for comparison. Required for tolerance rules (must include tolerance key). See the Rule Types Reference. |
collectors |
No | Creates CommandParser objects |
List of platform-specific command definitions (see below) |
Collector Fields¶
Each entry in the collectors list creates a CommandParser object linked to the parent validation rule.
| YAML Field | Required | Model Field | Description |
|---|---|---|---|
name |
Yes | CommandParser.parser |
Parser type: textfsm, napalm, ttp, or json |
platform |
Yes | CommandParser.platform |
The network_driver value of a Nautobot Platform (e.g., cisco_ios, arista_eos, juniper_junos). If no matching Platform exists, the collector is skipped with a warning. |
command |
No | CommandParser.command |
CLI command to execute on the device |
jmespath |
No | CommandParser.path |
JMESPath expression to extract data from parsed output |
napalm_getter |
No | CommandParser.napalm_getter |
NAPALM getter method name (e.g., get_facts, get_interfaces). Used when name is napalm. |
exclude |
No | CommandParser.exclude |
List of keys to exclude from comparison. Only valid with exact_match rule type. Cannot be combined with jmespath. |
Note
Each validation rule can have at most one collector per platform. The combination of (validation_rule, platform) must be unique.
Example: Validation Rules YAML Files¶
File: oc/rules/routing.yml
---
bgp_neighbor_state:
display_name: "BGP Neighbor State"
rule_type: "exact_match"
description: "Verify all BGP neighbor sessions remain in the same state"
collectors:
- name: "textfsm"
platform: "cisco_ios"
command: "show ip bgp summary"
jmespath: "[*].[$bgp_neigh$, state_pfxrcd]"
- name: "textfsm"
platform: "arista_eos"
command: "show ip bgp summary"
jmespath: "[*].[$bgp_neigh$, state_pfxrcd]"
- name: "textfsm"
platform: "juniper_junos"
command: "show bgp summary"
jmespath: "[*].[$peer_address$, received_routes]"
bgp_prefix_tolerance:
display_name: "BGP Prefix Count"
rule_type: "tolerance"
description: "Allow BGP received prefix counts to fluctuate within tolerance"
evaluate_args:
tolerance: 10
collectors:
- name: "textfsm"
platform: "cisco_ios"
command: "show ip bgp summary"
jmespath: "[*].[$bgp_neigh$, state_pfxrcd]"
ospf_neighbor_state:
display_name: "OSPF Neighbor State"
rule_type: "exact_match"
description: "Ensure OSPF adjacencies remain stable"
collectors:
- name: "textfsm"
platform: "cisco_ios"
command: "show ip ospf neighbor"
jmespath: "[*].[$neighbor_id$, state]"
- name: "textfsm"
platform: "arista_eos"
command: "show ip ospf neighbor"
jmespath: "[*].[$neighbor_id$, state]"
File: oc/rules/interfaces.yml
---
interface_status:
display_name: "Interface Status"
rule_type: "exact_match"
description: "Monitor interface operational state"
collectors:
- name: "napalm"
platform: "cisco_ios"
napalm_getter: "get_interfaces"
jmespath: "*.{is_up: is_up, is_enabled: is_enabled}"
- name: "napalm"
platform: "arista_eos"
napalm_getter: "get_interfaces"
jmespath: "*.{is_up: is_up, is_enabled: is_enabled}"
interface_counters:
display_name: "Interface Counters"
rule_type: "exact_match"
description: "Compare interface data excluding volatile statistics"
collectors:
- name: "napalm"
platform: "cisco_ios"
napalm_getter: "get_interfaces"
exclude:
- "tx_errors"
- "rx_errors"
- "tx_discards"
- "rx_discards"
File: oc/rules/system.yml
---
device_facts:
display_name: "Device Facts"
rule_type: "exact_match"
description: "Verify device facts have not changed"
collectors:
- name: "napalm"
platform: "cisco_ios"
napalm_getter: "get_facts"
jmespath: "{hostname: hostname, model: model, os_version: os_version}"
- name: "napalm"
platform: "arista_eos"
napalm_getter: "get_facts"
jmespath: "{hostname: hostname, model: model, os_version: os_version}"
ntp_sync:
display_name: "NTP Synchronization"
rule_type: "exact_match"
description: "Ensure NTP peers remain consistent"
collectors:
- name: "textfsm"
platform: "cisco_ios"
command: "show ntp associations"
jmespath: "[*].[$address$, ref_clock]"
- name: "textfsm"
platform: "juniper_junos"
command: "show ntp associations"
jmespath: "[*].[$remote$, refid]"
os_version_compliance:
display_name: "OS Version Compliance"
rule_type: "parameter_match"
description: "Check devices are running approved OS version"
evaluate_args:
params:
os_version: "17.12.2"
mode: "match"
collectors:
- name: "napalm"
platform: "cisco_ios"
napalm_getter: "get_facts"
jmespath: "os_version"
Validation Rule Groups YAML Format¶
Each YAML file in the rule-groups/ directory contains one or more groups as top-level keys. Groups reference validation rules by their display name (not the slug).
---
pre_change_checks:
display_name: "Pre-Change Validation" # optional, defaults to slug-derived name
description: "Rules to run before changes" # optional
validation_rules: # list of validation rule display names
- "BGP Neighbor State"
- "OSPF Neighbor State"
- "Interface Status"
- "Device Facts"
Warning
Rules referenced in a group must already exist in the database (i.e., the rules YAML files are processed before groups). If a referenced rule name is not found, a warning is logged and the rule is skipped — the group is still created with the remaining rules.
Group Fields¶
| YAML Field | Required | Model Field | Description |
|---|---|---|---|
display_name |
No | ValidationRuleGroup.name |
Human-readable name. Defaults to the slug with underscores replaced by spaces and title-cased. |
description |
No | ValidationRuleGroup.description |
Free-text description of the group |
validation_rules |
No | ValidationRuleGroup.validation_rules (M2M) |
List of validation rule display names to include in the group |
Example: Validation Rule Groups YAML Files¶
File: oc/rule-groups/change_management.yml
---
pre_change_validation:
display_name: "Pre-Change Validation"
description: "Comprehensive checks to run before a maintenance window"
validation_rules:
- "BGP Neighbor State"
- "OSPF Neighbor State"
- "Interface Status"
- "Device Facts"
- "NTP Synchronization"
routing_health:
display_name: "Routing Health"
description: "Focused routing protocol validation"
validation_rules:
- "BGP Neighbor State"
- "BGP Prefix Count"
- "OSPF Neighbor State"
platform_baseline:
display_name: "Platform Baseline"
description: "Hardware and software compliance checks"
validation_rules:
- "Device Facts"
- "OS Version Compliance"
Command Parsers Datasource¶
This datasource provides custom TextFSM and TTP parser templates that the app uses at runtime to parse CLI command output. This is useful when:
- You need a custom parser not available in ntc-templates
- You want to override an existing ntc-templates parser with a custom version
- You are using TTP templates (which are not included in ntc-templates)
Directory Structure¶
repository_root/
├── parsers/
│ ├── cisco_ios/
│ │ ├── show_version.textfsm
│ │ ├── show_ip_bgp_summary.textfsm
│ │ └── show_interfaces.ttp
│ ├── arista_eos/
│ │ ├── show_version.textfsm
│ │ └── show_ip_bgp_summary.ttp
│ └── juniper_junos/
│ └── show_bgp_summary.ttp
File Naming Convention¶
The app converts the CLI command to a filename by replacing spaces with underscores:
| CLI Command | Expected Filename |
|---|---|
show version |
show_version.textfsm or show_version.ttp |
show ip bgp summary |
show_ip_bgp_summary.textfsm or show_ip_bgp_summary.ttp |
show interfaces |
show_interfaces.textfsm or show_interfaces.ttp |
The file extension (.textfsm or .ttp) must match the parser type configured on the CommandParser object.
Parser File Path Resolution¶
At runtime, the app resolves parser file paths using a Jinja2 template. The default template renders to a path like cisco_ios/show_version, which is then appended to the parsers/ directory in the Git repository and given the appropriate file extension.
The full resolution path is: <repo>/parsers/<network_driver>/<command_filename>.<parser_type>
Example: For a device with platform cisco_ios running show ip bgp summary with a textfsm parser:
Customizing the Path Template¶
The path template can be customized via the GIT_PARSERS_PATH setting in your Nautobot configuration or via the Constance admin UI. Available template variables:
| Variable | Description |
|---|---|
{{ obj }} |
The device object |
{{ obj.platform.network_driver }} |
The platform's network driver (e.g., cisco_ios) |
{{ cmd }} |
The command converted to a filename (spaces replaced with underscores) |
Parser Lookup Behavior¶
When the app needs to parse command output, it follows this lookup order:
| Parser Type | Custom Git Template | Fallback |
|---|---|---|
| TextFSM | Checks Git repos for .textfsm file |
Falls back to ntc-templates built-in templates |
| TTP | Checks Git repos for .ttp file |
No fallback — fails if not found in a Git repo |
| NAPALM | N/A | Uses NAPALM getter directly |
| JSON | N/A | Parses JSON output directly |
Warning
TTP parsers must be provided through a Git repository. There is no built-in fallback for TTP templates. If a TTP template is not found, the command output parsing will fail.
Complete Example: Setting Up Both Datasources¶
Here is a complete example showing how to set up a single Git repository for validation rules, and a second repository for custom parser templates.
Repository 1: Validation Rules¶
Git Repository Configuration in Nautobot:
- Name:
Compliance Rules - Provided Contents:
Operational Compliance App Validation Rules
Repository layout:
compliance-rules/
├── oc/
│ ├── rules/
│ │ ├── routing.yml
│ │ ├── interfaces.yml
│ │ └── system.yml
│ └── rule-groups/
│ └── change_management.yml
Repository 2: Custom Parser Templates¶
Git Repository Configuration in Nautobot:
- Name:
Compliance Parsers - Provided Contents:
Operational Compliance App Command Parsers
Repository layout:
compliance-parsers/
├── parsers/
│ ├── cisco_ios/
│ │ ├── show_ip_bgp_summary.textfsm
│ │ └── show_ip_ospf_neighbor.textfsm
│ ├── arista_eos/
│ │ ├── show_ip_bgp_summary.textfsm
│ │ └── show_ip_ospf_neighbor.ttp
│ └── juniper_junos/
│ └── show_bgp_summary.ttp
Tip
You can also combine both content types into a single Git repository by selecting both Operational Compliance App Validation Rules and Operational Compliance App Command Parsers under Provided Contents when configuring the repository. In that case, the repository would contain both the oc/ directory and the parsers/ directory at the root level.