def test_response_parse_ttp(): response = Response("localhost", channel_input="show ip arp", genie_platform="iosxe") # example data lifted straight out of ttp docs ttp_template = """ interface {{ interface }} ip address {{ ip }}/{{ mask }} description {{ description }} ip vrf {{ vrf }} """ response_bytes = b""" interface Loopback0 description Router-id-loopback ip address 192.168.0.113/24 ! interface Vlan778 description CPE_Acces_Vlan ip address 2002::fd37/124 ip vrf CPE1 ! """ response.record_response(response_bytes) result = response.ttp_parse_output(template=ttp_template) assert result[0][0]["ip"] == "192.168.0.113"
def test_response_parse_ttp_fail(): response = Response("localhost", channel_input="show ip arp", genie_platform="iosxe") response_bytes = b"" response.record_response(response_bytes) assert response.ttp_parse_output(template="blah") == [{}]
def test_response_parse_textfsm_fail(): response = Response("localhost", channel_input="show ip arp", textfsm_platform="cisco_ios") response_bytes = b"" response.record_response(response_bytes) assert response.textfsm_parse_output() == []
def test_response_parse_genie_fail(): response = Response("localhost", channel_input="show ip arp", genie_platform="iosxe") response_bytes = b"" response.record_response(response_bytes) assert response.genie_parse_output() == []
def test_response_parse_textfsm_no_template(): response = Response("localhost", channel_input="show ip arp", textfsm_platform="potato") response_bytes = b"" response.record_response(response_bytes) assert response.textfsm_parse_output() == []
def test_record_response_unicodedecodeerror(): # this test validates that we catch unicdedecodeerror when decoding raw result response = Response("localhost", channel_input="show ip arp", genie_platform="iosxe") response_bytes = b"Manufacturer name :p\xb67\x038\x93\xa5\x03\x10\n" response.record_response(response_bytes) assert repr( response.result) == "'Manufacturer name :p¶7\\x038\\x93¥\\x03\\x10\\n'"
def test_response_parse_genie(): response = Response("localhost", channel_input="show ip arp", genie_platform="iosxe") response_bytes = b"""Protocol Address Age (min) Hardware Addr Type Interface Internet 172.31.254.1 - 0000.0c07.acfe ARPA Vlan254 Internet 172.31.254.2 - c800.84b2.e9c2 ARPA Vlan254 """ response.record_response(response_bytes) result = response.genie_parse_output() assert (result["interfaces"]["Vlan254"]["ipv4"]["neighbors"] ["172.31.254.1"]["ip"] == "172.31.254.1")
def test_response_parse_textfsm_string_path(): template = _textfsm_get_template("cisco_ios", "show ip arp").name response = Response("localhost", channel_input="show ip arp", textfsm_platform="cisco_ios") response_bytes = b"""Protocol Address Age (min) Hardware Addr Type Interface Internet 172.31.254.1 - 0000.0c07.acfe ARPA Vlan254 Internet 172.31.254.2 - c800.84b2.e9c2 ARPA Vlan254 """ response.record_response(response_bytes) result = response.textfsm_parse_output(template=template) assert result[0]["address"] == "172.31.254.1"
def test_response_parse_textfsm(parse_type): to_dict = parse_type[0] expected_result = parse_type[1] response = Response("localhost", channel_input="show ip arp", textfsm_platform="cisco_ios") response_bytes = b"""Protocol Address Age (min) Hardware Addr Type Interface Internet 172.31.254.1 - 0000.0c07.acfe ARPA Vlan254 Internet 172.31.254.2 - c800.84b2.e9c2 ARPA Vlan254 """ response.record_response(response_bytes) assert response.textfsm_parse_output(to_dict=to_dict)[0] == expected_result
def test_response_record_result(): response = Response("localhost", "ls -al") response_end_time = str(datetime.now())[:-7] response_bytes = b""" ls -al total 264 drwxr-xr-x 34 carl staff 1088 Jan 27 19:07 ./ drwxr-xr-x 21 carl staff 672 Jan 25 15:56 ../ -rw-r--r-- 1 carl staff 53248 Jan 27 19:07 .coverage drwxr-xr-x 12 carl staff 384 Jan 27 19:13 .git/""" response.record_response(response_bytes) assert str(response.finish_time)[:-7] == response_end_time assert response.result == response_bytes.decode() assert response.failed is False
def test_response_record_result_failed_when_failed(): response = Response("localhost", "ls -al", failed_when_contains=["!racecar!"]) response_end_time = str(datetime.now())[:-7] response_bytes = b""" ls -al total 264 drwxr-xr-x 34 carl staff 1088 Jan 27 19:07 ./ drwxr-xr-x 21 carl staff 672 Jan 25 15:56 ../ -rw-r--r-- 1 carl staff 53248 Jan 27 19:07 !racecar! drwxr-xr-x 12 carl staff 384 Jan 27 19:13 .git/""" response.record_response(response_bytes) assert str(response.finish_time)[:-7] == response_end_time assert response.result == response_bytes.decode() assert response.failed is True
def _post_send_command( raw_response: bytes, processed_response: bytes, response: Response ) -> Response: """ Handle post "send_command" tasks for consistency between sync/async versions Args: raw_response: raw response returned from the channel processed_response: processed response returned from the channel response: response object to update with channel results Returns: Response: Scrapli Response object Raises: N/A """ response.record_response(result=processed_response) response.raw_result = raw_response return response
def send_inputs_interact(self, channel_inputs: List[str], hidden_response: bool = False) -> Response: """ Send inputs in an interactive fashion, used to handle prompts that occur after an input. Args: channel_inputs: list of four string elements representing... channel_input - initial input to send expected_prompt - prompt to expect after initial input response - response to prompt final_prompt - final prompt to expect hidden_response: True/False response is hidden (i.e. password input) Returns: Response: scrapli Response object Raises: TypeError: if inputs is not tuple or list """ if not isinstance(channel_inputs, list): raise TypeError( f"`send_inputs_interact` expects a List, got {type(channel_inputs)}" ) channel_input, expectation, channel_response, finale = channel_inputs response = Response( self.transport.host, channel_input, expectation=expectation, channel_response=channel_response, finale=finale, ) raw_result, processed_result = self._send_input_interact( channel_input, expectation, channel_response, finale, hidden_response) response.raw_result = raw_result.decode() response.record_response(processed_result.decode().strip()) return response
def send_command( self, command: str, strip_prompt: bool = True, failed_when_contains: Optional[Union[str, List[str]]] = None, ) -> Response: """ Send a command Args: command: string to send to device in privilege exec mode strip_prompt: True/False strip prompt from returned output failed_when_contains: string or list of strings indicating failure if found in response Returns: Response: Scrapli Response object Raises: TypeError: if command is anything but a string """ if not isinstance(command, str): raise TypeError( f"`send_command` expects a single string, got {type(command)}. " "to send a list of commands use the `send_commands` method instead." ) response = Response(self.transport.host, channel_input=command, failed_when_contains=failed_when_contains) raw_response, processed_response = self.channel.send_input( command, strip_prompt) response.record_response(processed_response) response.raw_result = raw_response return response