dmulyalin / ttp

Template Text Parser
MIT License
348 stars 34 forks source link

ttp not working inside a function #112

Open chustm opened 11 months ago

chustm commented 11 months ago

Hi there, I'm having an issue with ttp as it's working fine when the Netmiko call is in the main body, but when I move all the code, including the Netmiko call, inside a function the dictionary returned is empty. Or even if I move ttp code to a function, and keep Netmiko call on the amin one, sending data through a function. BUT, if instead using Netmiko to get the data I use plain text as data input, it works either way inside or outside a function.

Script with Netmiko and no Function returns proper dict:

from ttp import ttp
from netmiko import ConnectHandler
import json

emea_cred = 'admin'
emea_psw = 'Password0'
device = {"device_type":"cisco_ios","ip":"10.1.1.1","username":emea_cred,"password":emea_psw,"fast_cli":"False"}

with ConnectHandler(**device) as net_connect:
    wlc_hostname = net_connect.find_prompt()[:-1]
    data = net_connect.send_command('show run | inc (^wlan.+)_([0-9]+)_([A-Za-z0-9]+)$')
    print (data)

template = """
<template name="wlan_profile_summ">
<group name="{{ wlan_profile }}">
wlan {{ wlan_profile | _start_ }} {{ wlan_id }} {{ ssid }}
</group>
</template>
"""

parser2 = ttp(data, template)
parser2.parse()
cisco_wlanTemplates2 = parser2.result(structure="flat_list")
print(json.dumps(cisco_wlanTemplates2, sort_keys=True, indent=5, separators=(',', ': ')))

image

Script with Netmiko inside Function returns empty dict:

from ttp import ttp
from netmiko import ConnectHandler
import json

def parse_cisco_wlans():
    emea_cred = 'admin'
    emea_psw = 'Password0'
    device = {"device_type":"cisco_ios","ip":"10.1.1.1","username":emea_cred,"password":emea_psw,"fast_cli":"False"}

    with ConnectHandler(**device) as net_connect:
        wlc_hostname = net_connect.find_prompt()[:-1]
        data1 = net_connect.send_command('show run | inc (^wlan.+)_([0-9]+)_([A-Za-z0-9]+)$')

    template = """
    <template name="wlan_profile_summ">
    <group name="{{ wlan_profile }}">
    wlan {{ wlan_profile | _start_ }} {{ wlan_id }} {{ ssid }}
    </group>
    </template>
    """
    print (data1)
    parser2 = ttp(data1, template)
    parser2.parse()

    cisco_wlanTemplates2 = parser2.result(structure="flat_list")
    print(json.dumps(cisco_wlanTemplates2, sort_keys=True, indent=5, separators=(',', ': ')))

def main():
        parse_cisco_wlans()
if __name__ == "__main__":
    main()

image

Script with plain data and no Function returns proper dict:

from ttp import ttp
import json

data = """
wlan IOT_psk 61 IoTNet
wlan CORP_wpa2 29 CorpNet
wlan CORP_wpa3 23 CorpNet
wlan IOT_dot1x 62 IoTNet
wlan CORP_wpa23 21 CorpNet
wlan GUEST_local 49 GuestNet
wlan XRNET_dot1x 79 XRNet
wlan VOICE_psk_ft 59 VoiceNet
wlan GUEST_central 48 GuestNet
wlan BYOD_wpa2_local 39 DeviceNet
wlan BYOD_wpa23_local 31 DeviceNet
wlan CORP_wpa2_24only 28 CorpNet
wlan BYOD_wpa2_central 38 DeviceNet
wlan GUEST_wpa23_local 41 GuestNet
wlan BYOD_wpa23_central 32 DeviceNet
wlan GUEST_wpa23_central 42 GuestNet
"""

template = """
<template name="wlan_profile_summ">
<group name="{{ wlan_profile }}">
wlan {{ wlan_profile | _start_ }} {{ wlan_id }} {{ ssid }}
</group>
</template>
"""

parser2 = ttp(data, template)
parser2.parse()

cisco_wlanTemplates2 = parser2.result(structure="flat_list")
print(json.dumps(cisco_wlanTemplates2, sort_keys=True, indent=5, separators=(',', ': ')))

Script with plain data inside Function returns proper dict:

from ttp import ttp
import json

def parse_cisco_wlans():
    data = """
    wlan IOT_psk 61 IoTNet
    wlan CORP_wpa2 29 CorpNet
    wlan CORP_wpa3 23 CorpNet
    wlan IOT_dot1x 62 IoTNet
    wlan CORP_wpa23 21 CorpNet
    wlan GUEST_local 49 GuestNet
    wlan XRNET_dot1x 79 XRNet
    wlan VOICE_psk_ft 59 VoiceNet
    wlan GUEST_central 48 GuestNet
    wlan BYOD_wpa2_local 39 DeviceNet
    wlan BYOD_wpa23_local 31 DeviceNet
    wlan CORP_wpa2_24only 28 CorpNet
    wlan BYOD_wpa2_central 38 DeviceNet
    wlan GUEST_wpa23_local 41 GuestNet
    wlan BYOD_wpa23_central 32 DeviceNet
    wlan GUEST_wpa23_central 42 GuestNet
    """

    template = """
    <template name="wlan_profile_summ">
    <group name="{{ wlan_profile }}">
    wlan {{ wlan_profile | _start_ }} {{ wlan_id }} {{ ssid }}
    </group>
    </template>
    """
    print (data)

    parser = ttp(data, template)
    parser.parse()

    cisco_wlanTemplates = parser.result(structure="flat_list")
    print(json.dumps(cisco_wlanTemplates, sort_keys=True, indent=5, separators=(',', ': ')))

def main():
        parse_cisco_wlans()

if __name__ == "__main__":
    main()
chustm commented 11 months ago

I finaly got this working. It was only moving the "template" variable out of the function and from main, and then simply call it:

import json

template = """
<template name="wlan_profile_summ">
<group name="{{ wlan_profile }}">
wlan {{ wlan_profile | _start_ }} {{ wlan_id | DIGIT }} {{ ssid }}
</group>
</template>
"""

def parse_cisco_wlans(wlcList,ssid,newPsk):
    for device in wlcList:
        try:
            with ConnectHandler(**device) as net_connect:
                wlc_hostname = net_connect.find_prompt()[:-1]
                print ('=========> Connecting to ',wlc_hostname)
                data = net_connect.send_command('show run | inc (^wlan.+)_([0-9]+)_([A-Za-z0-9]+)$')

                parser = ttp(data, template)
                parser.parse()

                cisco_wlanTemplates = parser.result(structure="flat_list")
(...)
pdimop commented 10 months ago

when you moved the template variable in the function you accidentaly indented all the strings, thats why it was not matching anything. If you want to move the template back in the function write something like this:

    template = """
<template name="wlan_profile_summ">
<group name="{{ wlan_profile }}">
wlan {{ wlan_profile | _start_ }} {{ wlan_id }} {{ ssid }}
</group>
</template>
"""