From 2e83c1eb53e9378873eb2192f85e717df84b9cd0 Mon Sep 17 00:00:00 2001 From: aapostoliuk Date: Tue, 18 Oct 2022 15:27:27 +0300 Subject: T4496: Added lists of values in the help of op-mode ping command Added list of possible VRFs in the help of the ping command Added list of possible interfaces in the help of the ping command Changed, if an option was selected before in the ping command, it does not appear in possible completion. Added error message when an unexpected option was selected. --- src/op_mode/ping.py | 90 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 17 deletions(-) (limited to 'src/op_mode/ping.py') diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py index 60bbc0c78..5e5b95a0a 100755 --- a/src/op_mode/ping.py +++ b/src/op_mode/ping.py @@ -18,6 +18,32 @@ import os import sys import socket import ipaddress +import json +from vyos.util import cmd, rc_cmd +from vyos.ifconfig import Section + + +def interface_list() -> list: + """ + Get list of interfaces in system + :rtype: list + """ + return Section.interfaces() + + +def vrf_list() -> list: + """ + Get list of VRFs in system + :rtype: list + """ + result = cmd(f'sudo ip --json --brief link show type vrf') + data = json.loads(result) + vrflist: list = [] + for o in data: + if 'ifname' in o: + vrflist.append(o['ifname']) + return vrflist + options = { 'audible': { @@ -63,6 +89,7 @@ options = { 'interface': { 'ping': '{command} -I {value}', 'type': '', + 'helpfunction': interface_list, 'help': 'Source interface' }, 'interval': { @@ -128,6 +155,7 @@ options = { 'ping': 'sudo ip vrf exec {value} {command}', 'type': '', 'help': 'Use specified VRF table', + 'helpfunction': vrf_list, 'dflt': 'default', }, 'verbose': { @@ -142,20 +170,33 @@ ping = { } -class List (list): - def first (self): +class List(list): + def first(self): return self.pop(0) if self else '' def last(self): return self.pop() if self else '' - def prepend(self,value): - self.insert(0,value) + def prepend(self, value): + self.insert(0, value) + + +def completion_failure(option: str) -> None: + """ + Shows failure message after TAB when option is wrong + :param option: failure option + :type str: + """ + sys.stderr.write('\n\n Invalid option: {}\n\n'.format(option)) + sys.stdout.write('') + sys.exit(1) def expension_failure(option, completions): reason = 'Ambiguous' if completions else 'Invalid' - sys.stderr.write('\n\n {} command: {} [{}]\n\n'.format(reason,' '.join(sys.argv), option)) + sys.stderr.write( + '\n\n {} command: {} [{}]\n\n'.format(reason, ' '.join(sys.argv), + option)) if completions: sys.stderr.write(' Possible completions:\n ') sys.stderr.write('\n '.join(completions)) @@ -196,28 +237,44 @@ if __name__ == '__main__': if host == '--get-options': args.first() # pop ping args.first() # pop IP + usedoptionslist = [] while args: - option = args.first() - - matched = complete(option) + option = args.first() # pop option + matched = complete(option) # get option parameters + usedoptionslist.append(option) # list of used options + # Select options if not args: + # remove from Possible completions used options + for o in usedoptionslist: + if o in matched: + matched.remove(o) sys.stdout.write(' '.join(matched)) sys.exit(0) - if len(matched) > 1 : + if len(matched) > 1: sys.stdout.write(' '.join(matched)) sys.exit(0) + # If option doesn't have value + if matched: + if options[matched[0]]['type'] == 'noarg': + continue + else: + # Unexpected option + completion_failure(option) - if options[matched[0]]['type'] == 'noarg': - continue - - value = args.first() + value = args.first() # pop option's value if not args: matched = complete(option) - sys.stdout.write(options[matched[0]]['type']) + helplines = options[matched[0]]['type'] + # Run helpfunction to get list of possible values + if 'helpfunction' in options[matched[0]]: + result = options[matched[0]]['helpfunction']() + if result: + helplines = '\n' + ' '.join(result) + sys.stdout.write(helplines) sys.exit(0) - for name,option in options.items(): + for name, option in options.items(): if 'dflt' in option and name not in args: args.append(name) args.append(option['dflt']) @@ -234,8 +291,7 @@ if __name__ == '__main__': except ValueError: sys.exit(f'ping: Unknown host: {host}') - command = convert(ping[version],args) + command = convert(ping[version], args) # print(f'{command} {host}') os.system(f'{command} {host}') - -- cgit v1.2.3