Skip to content

[IOS-XR] indent_adjust rule for "template" corrupts indentation when used as leaf param inside flow exporter-map #205

@Kani999

Description

@Kani999

Version

hier-config 3.4.1

Platform

Platform.CISCO_XR

Error

DuplicateChildError: Found a duplicate section: ('flow exporter-map EXPORTER1', 'route-policy POLICY1', 'endif')

Minimal Reproduction

from hier_config import get_hconfig, Platform

text = '''flow exporter-map EXPORTER1
 version v9
  template timeout 60
 !
 transport udp 9999
!
route-policy POLICY1
  if (destination in PREFIX-SET1) then
    drop
  endif
  if (destination in PREFIX-SET2) then
    done
  endif
  drop
end-policy
!
'''
get_hconfig(Platform.CISCO_XR, text)

Stack trace:

File ".../hier_config/base.py", line 86, in add_child
    raise DuplicateChildError(message)
hier_config.exceptions.DuplicateChildError: Found a duplicate section: ('flow exporter-map EXPORTER1', 'route-policy POLICY1', 'endif')

Root Cause Analysis

The IOS-XR driver defines an indent_adjust rule in hier_config/platforms/cisco_xr/driver.py (lines 106–110):

  • start_expression="^\s*template" → increments indent_adjust by 1
  • end_expression="^\s*end-template" → decrements it back

In flow exporter-map blocks, IOS-XR uses template timeout 60 as a leaf parameter — it is not a block opener and has no matching end-template. When the parser encounters this line:

  1. indent_adjust is incremented to +1.
  2. No end-template ever follows, so indent_adjust is permanently stuck at +1 for the remainder of the file.
  3. All subsequent top-level blocks (route-policy POLICY1, etc.) are parsed as if they are children of the last open block (flow exporter-map EXPORTER1).
  4. parent_allows_duplicate_child only permits duplicates when the direct parent starts with "route-policy" — but the parent is now flow exporter-map EXPORTER1, so endif appearing twice raises DuplicateChildError.

Suggested Fix Options

Option 1 — Narrow the start_expression to exclude template timeout (and similar leaf forms):

start_expression=r"^\s*template(?!\s+timeout)"

This uses a negative lookahead so lines like template timeout 60 no longer trigger the indent increment.

Option 2 — Scope the rule so it only fires when the current parent context is a template block:

Require the enclosing parent to be a template definition before bumping indent_adjust, avoiding false positives from leaf uses of the template keyword in other block types.

Driver File

hier_config/platforms/cisco_xr/driver.py, lines 106–110

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions