dmulyalin / ttp

Template Text Parser
MIT License
351 stars 34 forks source link

How to correlate/enforce previously matched attribute? #93

Open vlisjak opened 2 years ago

vlisjak commented 2 years ago

Hi Denis,

is there a way to match an attribute, then modify that attribute, and finally use the modified attribute when matching at later lines?

In below example, I would like to save router-id (1.1.1.64), and then use only last octet (64) to make sure that RP_LOOP2BGP is called with correct argument:

router bgp 6805
 bgp router-id 1.1.1.64
 address-family ipv4 unicast
  dynamic-med interval 0
  network 1.1.1.64/32 route-policy RP_LOOP2BGP(64)
!

Something like:

<macro>
def add_last_octet(data):
  return(data, {"last_octet": '64'})
</macro>

<group name="config">
<group name="routing.bgp">

router bgp {{ asn }}
 bgp router-id {{ router_id | macro(add_last_octet) }}
 <group name="ipv4_af">
 address-family ipv4 unicast {{ _start_ }}{{ _exact_ }}
  dynamic-med interval {{ dynamic_med_interval | equal('0') | default(MISSING)}}
  network {{ network | equal(router_id) | default(MISSING) }}/32 route-policy RP_LOOP2BGP({{ RP_LOOP2BGP | equal(last_octet) | default(MISSING) }})
</group>
 !
vlisjak commented 2 years ago

FYI - I guess I found a (not so elegant) solution using macros:

@dmulyalin, do you perhaps see a better way of doing this?

<macro>
def save_last_octet(data):
  tmp = data.split('.')[3]
  _ttp_['vars']['last_octet'] = tmp 
  return(data, {"last_octet": tmp})

def save_router_id(data):
  tmp = data
  _ttp_['vars']['router_id'] = tmp 
  return(data, {"router_id": tmp})

def is_router_id_32(data):
  if 'router_id' in _ttp_['vars']:
    if data == _ttp_['vars']['router_id'] + '/32':
      return(True)
  return(False)

def is_last_octet(data):
  if 'last_octet' in _ttp_['vars']:
    if data == _ttp_['vars']['last_octet']:
      return(True)
  return(False)
</macro>

<group name="config">
<group name="routing.bgp">

router bgp {{ asn }}
 bgp router-id {{ router_id | macro("save_router_id") | macro("save_last_octet")  | default(MISSING) }}

 <group name="af_ipv4">
 address-family ipv4 unicast {{ _start_ |  _exact_ }}
  dynamic-med interval {{ dynamic_med_interval | equal('0') | default(MISSING)}}
  network {{ network | macro(is_router_id_32) | default(MISSING) }} route-policy {{ network_rpl | equal("RP_LOOP2BGP") | default(MISSING) }}({{ network_rpl_arg | macro(is_last_octet) | default(MISSING)}})

 !{{ _end_ }}
 </group>
dmulyalin commented 1 year ago

Yeah, using macro is the most strightforward path here, one suggestion is replacing this

bgp router-id {{ router_id | macro("save_router_id") | macro("save_last_octet")  | default(MISSING) }}

with this:

bgp router-id {{ router_id | record("router_id ") | macro("save_last_octet")  | default(MISSING) }}

should give same results