Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Yes, subparsers can improve a lot of things. You could also use if __name__ == '__main__': if __name__ == '__main__': even though it is not necessary for this kind of "executable only" script.

Yes, subparsers can improve a lot of things. You could also use if __name__ == '__main__': even though it is not necessary for this kind of "executable only" script.

Yes, subparsers can improve a lot of things. You could also use if __name__ == '__main__': even though it is not necessary for this kind of "executable only" script.

deleted 4 characters in body
Source Link
#!/usr/bin/env python3
"""Script to generate searches on the ArcSight Logger"""
import arcsightrest
import argparse
def parse_command_line():
 parser = argparse.ArgumentParser(
 description='Script used to send search queries '
 'to ArcSight Logger API')
 
 # General informations
 parser.add_argument('target', help='IP Address of the Loggger')
 parser.add_argument('username', help='Username to access the logger')
 parser.add_argument('password', help='Password to access the logger')
 parser.add_argument('-s', '--unsecuressl', action='store_true',
 help='Disable ssl warnings')
 
 # Commands
 command_subparser = parser.add_subparsers(dest='action', metavar='action')
 # Query
 query = command_subparser.add_parser('query', help='search informations')
 query.add_argument('query', help='Query to be used in the search')
 query.add_argument(
 '--starttime', help='From which time the query should look')
 query.add_argument('--endtime', help='To which time the query should look')
 query.add_argument(
 '--discoverfields', help='Try to discover fields in the events found')
 query.add_argument('--summaryfields', help='The list of fields')
 query.add_argument('--fieldssummary', help='Use fields summary')
 query.add_argument(
 '--localsearch', help='Indicates the search is local only')
 query.add_argument('--searchtype', help='Interactive search or not')
 query.add_argument(
 '--timeout', help='The number of milliseconds to keep the '
 'search after it has finished running')
 query.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Past search
 search = command_subparser.add_parser(
 'search', help='actions on previous search')
 search.add_argument(
 'search_id', help='Search id of a currently running search')
 search_subparser = search.add_subparsers(
 dest='search_kind', metavar='kind')
 
 # Status settings
 status = search_subparser.add_parser(
 'status', help='Status of running search')
 status.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Histogram Settings
 histogram = search_subparser.add_parser(
 'histogram', help='Get histogram overview of specific earch')
 
 # Drilldown Settings
 drilldown = search_subparser.add_parser(
 'drilldown', help='Gets drilldown of specific search')
 drilldown.add_argument(
 '--starttime', help='From which time the search should look')
 drilldown.add_argument(
 '--endtime', help='To which time the search should look')
 # Event Settings
 event = search_subparser.add_parser(
 'event', help='Get all information from a finished search')
 event.add_argument(
 '--dir', help='Sort direction based on event time')
 event.add_argument('--field')
 event.add_argument('--length')
 event.add_argument('--offset')
 
 # Raw Event Settings
 raw_event = search_subparser.add_parser(
 'rawevent', help='Get the raw event results from a search')
 raw_event.add_argument(
 'row_id', help='Specific row id for the raw event')
 
 # Chart Data Settings
 chart_data = search_subparser.add_parser(
 'chartdata', help='Returns data in a chart format')
 chart_data.add_argument('--field')
 chart_data.add_argument('--length')
 chart_data.add_argument('--offset')
 # Retrieve all arguments
 args = parser.parse_args()
 if args.commandaction is None:
 # Not sure if this one is mandatory
 parser.error('you should provide an action to execute')
 elif args.commandaction == 'search' and args.search_kind is None:
 parser.error(
 "you should provide the kind of search "
 "when performing the 'search' action")
 else:
 return args
def query(arc, args):
 search_id, response = arc.search(
 args.query,
 start_time=args.starttime,
 end_time=args.endtime,
 discover_fields=args.discoverfields,
 summary_fields=args.summaryfields,
 fields_summary=args.fieldssummary,
 local_search=args.localsearch,
 search_type=args.searchtype,
 timeout=args.timeout)
 if args.wait:
 arc.wait(search_id)
 return search_id
def search(arc, search_id, kind, args):
 if kind == 'histogram':
 return arc.histogram(search_id=search_id)
 
 if kind == 'drilldown':
 return arc.drilldown(
 search_id=search_id,
 start_time=args.starttime,
 end_time=args.endtime)
 
 if kind == 'event':
 return arc.events(
 search_id=search_id,
 dir=args.dir,
 fields=args.fields,
 length=args.length,
 offset=args.offset)
 if kind == 'rawevent':
 return arc.raw_events(search_id, row_ids=args.rowids)
 
 if kind == 'chartdata':
 return arc.events(
 search_id=search_id,
 length=args.length,
 offset=args.offset)
 
 if kind == 'status':
 if args.wait:
 arc.wait(search_id)
 return arc.search_complete(search_id=search_id)
if __name__ == '__main__':
 args = parse_command_line()
 # Sets the target Logger Server
 arcsightrest.ArcsightLogger.TARGET = args.target
 arc = arcsightrest.ArcsightLogger(
 args.username,
 args.password,
 args.unsecuressl)
 if args.commandaction == 'query':
 print(query(arc, args))
 elif args.commandaction == 'search':
 print(search(arc, args.search_id, args.search_kind, args))
#!/usr/bin/env python3
"""Script to generate searches on the ArcSight Logger"""
import arcsightrest
import argparse
def parse_command_line():
 parser = argparse.ArgumentParser(
 description='Script used to send search queries '
 'to ArcSight Logger API')
 
 # General informations
 parser.add_argument('target', help='IP Address of the Loggger')
 parser.add_argument('username', help='Username to access the logger')
 parser.add_argument('password', help='Password to access the logger')
 parser.add_argument('-s', '--unsecuressl', action='store_true',
 help='Disable ssl warnings')
 
 # Commands
 command_subparser = parser.add_subparsers(dest='action', metavar='action')
 # Query
 query = command_subparser.add_parser('query', help='search informations')
 query.add_argument('query', help='Query to be used in the search')
 query.add_argument(
 '--starttime', help='From which time the query should look')
 query.add_argument('--endtime', help='To which time the query should look')
 query.add_argument(
 '--discoverfields', help='Try to discover fields in the events found')
 query.add_argument('--summaryfields', help='The list of fields')
 query.add_argument('--fieldssummary', help='Use fields summary')
 query.add_argument(
 '--localsearch', help='Indicates the search is local only')
 query.add_argument('--searchtype', help='Interactive search or not')
 query.add_argument(
 '--timeout', help='The number of milliseconds to keep the '
 'search after it has finished running')
 query.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Past search
 search = command_subparser.add_parser(
 'search', help='actions on previous search')
 search.add_argument(
 'search_id', help='Search id of a currently running search')
 search_subparser = search.add_subparsers(
 dest='search_kind', metavar='kind')
 
 # Status settings
 status = search_subparser.add_parser(
 'status', help='Status of running search')
 status.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Histogram Settings
 histogram = search_subparser.add_parser(
 'histogram', help='Get histogram overview of specific earch')
 
 # Drilldown Settings
 drilldown = search_subparser.add_parser(
 'drilldown', help='Gets drilldown of specific search')
 drilldown.add_argument(
 '--starttime', help='From which time the search should look')
 drilldown.add_argument(
 '--endtime', help='To which time the search should look')
 # Event Settings
 event = search_subparser.add_parser(
 'event', help='Get all information from a finished search')
 event.add_argument(
 '--dir', help='Sort direction based on event time')
 event.add_argument('--field')
 event.add_argument('--length')
 event.add_argument('--offset')
 
 # Raw Event Settings
 raw_event = search_subparser.add_parser(
 'rawevent', help='Get the raw event results from a search')
 raw_event.add_argument(
 'row_id', help='Specific row id for the raw event')
 
 # Chart Data Settings
 chart_data = search_subparser.add_parser(
 'chartdata', help='Returns data in a chart format')
 chart_data.add_argument('--field')
 chart_data.add_argument('--length')
 chart_data.add_argument('--offset')
 # Retrieve all arguments
 args = parser.parse_args()
 if args.command is None:
 # Not sure if this one is mandatory
 parser.error('you should provide an action to execute')
 elif args.command == 'search' and args.search_kind is None:
 parser.error(
 "you should provide the kind of search "
 "when performing the 'search' action")
 else:
 return args
def query(arc, args):
 search_id, response = arc.search(
 args.query,
 start_time=args.starttime,
 end_time=args.endtime,
 discover_fields=args.discoverfields,
 summary_fields=args.summaryfields,
 fields_summary=args.fieldssummary,
 local_search=args.localsearch,
 search_type=args.searchtype,
 timeout=args.timeout)
 if args.wait:
 arc.wait(search_id)
 return search_id
def search(arc, search_id, kind, args):
 if kind == 'histogram':
 return arc.histogram(search_id=search_id)
 
 if kind == 'drilldown':
 return arc.drilldown(
 search_id=search_id,
 start_time=args.starttime,
 end_time=args.endtime)
 
 if kind == 'event':
 return arc.events(
 search_id=search_id,
 dir=args.dir,
 fields=args.fields,
 length=args.length,
 offset=args.offset)
 if kind == 'rawevent':
 return arc.raw_events(search_id, row_ids=args.rowids)
 
 if kind == 'chartdata':
 return arc.events(
 search_id=search_id,
 length=args.length,
 offset=args.offset)
 
 if kind == 'status':
 if args.wait:
 arc.wait(search_id)
 return arc.search_complete(search_id=search_id)
if __name__ == '__main__':
 args = parse_command_line()
 # Sets the target Logger Server
 arcsightrest.ArcsightLogger.TARGET = args.target
 arc = arcsightrest.ArcsightLogger(
 args.username,
 args.password,
 args.unsecuressl)
 if args.command == 'query':
 print(query(arc, args))
 elif args.command == 'search':
 print(search(arc, args.search_id, args.search_kind, args))
#!/usr/bin/env python3
"""Script to generate searches on the ArcSight Logger"""
import arcsightrest
import argparse
def parse_command_line():
 parser = argparse.ArgumentParser(
 description='Script used to send search queries '
 'to ArcSight Logger API')
 
 # General informations
 parser.add_argument('target', help='IP Address of the Loggger')
 parser.add_argument('username', help='Username to access the logger')
 parser.add_argument('password', help='Password to access the logger')
 parser.add_argument('-s', '--unsecuressl', action='store_true',
 help='Disable ssl warnings')
 
 # Commands
 command_subparser = parser.add_subparsers(dest='action', metavar='action')
 # Query
 query = command_subparser.add_parser('query', help='search informations')
 query.add_argument('query', help='Query to be used in the search')
 query.add_argument(
 '--starttime', help='From which time the query should look')
 query.add_argument('--endtime', help='To which time the query should look')
 query.add_argument(
 '--discoverfields', help='Try to discover fields in the events found')
 query.add_argument('--summaryfields', help='The list of fields')
 query.add_argument('--fieldssummary', help='Use fields summary')
 query.add_argument(
 '--localsearch', help='Indicates the search is local only')
 query.add_argument('--searchtype', help='Interactive search or not')
 query.add_argument(
 '--timeout', help='The number of milliseconds to keep the '
 'search after it has finished running')
 query.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Past search
 search = command_subparser.add_parser(
 'search', help='actions on previous search')
 search.add_argument(
 'search_id', help='Search id of a currently running search')
 search_subparser = search.add_subparsers(
 dest='search_kind', metavar='kind')
 
 # Status settings
 status = search_subparser.add_parser(
 'status', help='Status of running search')
 status.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Histogram Settings
 histogram = search_subparser.add_parser(
 'histogram', help='Get histogram overview of specific earch')
 
 # Drilldown Settings
 drilldown = search_subparser.add_parser(
 'drilldown', help='Gets drilldown of specific search')
 drilldown.add_argument(
 '--starttime', help='From which time the search should look')
 drilldown.add_argument(
 '--endtime', help='To which time the search should look')
 # Event Settings
 event = search_subparser.add_parser(
 'event', help='Get all information from a finished search')
 event.add_argument(
 '--dir', help='Sort direction based on event time')
 event.add_argument('--field')
 event.add_argument('--length')
 event.add_argument('--offset')
 
 # Raw Event Settings
 raw_event = search_subparser.add_parser(
 'rawevent', help='Get the raw event results from a search')
 raw_event.add_argument(
 'row_id', help='Specific row id for the raw event')
 
 # Chart Data Settings
 chart_data = search_subparser.add_parser(
 'chartdata', help='Returns data in a chart format')
 chart_data.add_argument('--field')
 chart_data.add_argument('--length')
 chart_data.add_argument('--offset')
 # Retrieve all arguments
 args = parser.parse_args()
 if args.action is None:
 # Not sure if this one is mandatory
 parser.error('you should provide an action to execute')
 elif args.action == 'search' and args.search_kind is None:
 parser.error(
 "you should provide the kind of search "
 "when performing the 'search' action")
 else:
 return args
def query(arc, args):
 search_id, response = arc.search(
 args.query,
 start_time=args.starttime,
 end_time=args.endtime,
 discover_fields=args.discoverfields,
 summary_fields=args.summaryfields,
 fields_summary=args.fieldssummary,
 local_search=args.localsearch,
 search_type=args.searchtype,
 timeout=args.timeout)
 if args.wait:
 arc.wait(search_id)
 return search_id
def search(arc, search_id, kind, args):
 if kind == 'histogram':
 return arc.histogram(search_id=search_id)
 
 if kind == 'drilldown':
 return arc.drilldown(
 search_id=search_id,
 start_time=args.starttime,
 end_time=args.endtime)
 
 if kind == 'event':
 return arc.events(
 search_id=search_id,
 dir=args.dir,
 fields=args.fields,
 length=args.length,
 offset=args.offset)
 if kind == 'rawevent':
 return arc.raw_events(search_id, row_ids=args.rowids)
 
 if kind == 'chartdata':
 return arc.events(
 search_id=search_id,
 length=args.length,
 offset=args.offset)
 
 if kind == 'status':
 if args.wait:
 arc.wait(search_id)
 return arc.search_complete(search_id=search_id)
if __name__ == '__main__':
 args = parse_command_line()
 # Sets the target Logger Server
 arcsightrest.ArcsightLogger.TARGET = args.target
 arc = arcsightrest.ArcsightLogger(
 args.username,
 args.password,
 args.unsecuressl)
 if args.action == 'query':
 print(query(arc, args))
 elif args.action == 'search':
 print(search(arc, args.search_id, args.search_kind, args))
Source Link

Yes, subparsers can improve a lot of things. You could also use if __name__ == '__main__': even though it is not necessary for this kind of "executable only" script.

The important thing being that, using subparsers, you can limit the amount of available options to the action you are performing.

Moreover, you should consider using positional arguments rather than optional ones + required=True. It feels cleaner on the help message.


Looking at your commands, you have two possibilities:

  • use only one subparser that will provide a parser for each of your commands (login, query, status, histogram, ...);
  • or use two subparsers: one providing the login, query and search commands and a second one under search to provide the various kind of searches.

Usage would be:

$ python script.py <target> <username> <password> [-s] # login
$ python script.py <target> <username> <password> [-s] query <query> [options]
$ python script.py <target> <username> <password> [-s] status <search_id> [-w]
$ python script.py <target> <username> <password> [-s] histogram <search_id> 
etc...

The disadvantage being that you need to specify the search id for each search parser. Or

$ python script.py <target> <username> <password> [-s] # login
$ python script.py <target> <username> <password> [-s] query <query> [options]
$ python script.py <target> <username> <password> [-s] search <search_id> status [-w]
$ python script.py <target> <username> <password> [-s] search <search_id> histogram
etc...

where you can factorize the definition of search_id to a common search parser but you will put the burden on the user by having they to provide a longer command line.


I’ll show the second approach, though, as it is easy to get back to the first one from there:

#!/usr/bin/env python3
"""Script to generate searches on the ArcSight Logger"""
import arcsightrest
import argparse
def parse_command_line():
 parser = argparse.ArgumentParser(
 description='Script used to send search queries '
 'to ArcSight Logger API')
 
 # General informations
 parser.add_argument('target', help='IP Address of the Loggger')
 parser.add_argument('username', help='Username to access the logger')
 parser.add_argument('password', help='Password to access the logger')
 parser.add_argument('-s', '--unsecuressl', action='store_true',
 help='Disable ssl warnings')
 
 # Commands
 command_subparser = parser.add_subparsers(dest='action', metavar='action')
 # Query
 query = command_subparser.add_parser('query', help='search informations')
 query.add_argument('query', help='Query to be used in the search')
 query.add_argument(
 '--starttime', help='From which time the query should look')
 query.add_argument('--endtime', help='To which time the query should look')
 query.add_argument(
 '--discoverfields', help='Try to discover fields in the events found')
 query.add_argument('--summaryfields', help='The list of fields')
 query.add_argument('--fieldssummary', help='Use fields summary')
 query.add_argument(
 '--localsearch', help='Indicates the search is local only')
 query.add_argument('--searchtype', help='Interactive search or not')
 query.add_argument(
 '--timeout', help='The number of milliseconds to keep the '
 'search after it has finished running')
 query.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Past search
 search = command_subparser.add_parser(
 'search', help='actions on previous search')
 search.add_argument(
 'search_id', help='Search id of a currently running search')
 search_subparser = search.add_subparsers(
 dest='search_kind', metavar='kind')
 
 # Status settings
 status = search_subparser.add_parser(
 'status', help='Status of running search')
 status.add_argument(
 '--wait', action='store_true', help='Wait for search to finish')
 
 # Histogram Settings
 histogram = search_subparser.add_parser(
 'histogram', help='Get histogram overview of specific earch')
 
 # Drilldown Settings
 drilldown = search_subparser.add_parser(
 'drilldown', help='Gets drilldown of specific search')
 drilldown.add_argument(
 '--starttime', help='From which time the search should look')
 drilldown.add_argument(
 '--endtime', help='To which time the search should look')
 # Event Settings
 event = search_subparser.add_parser(
 'event', help='Get all information from a finished search')
 event.add_argument(
 '--dir', help='Sort direction based on event time')
 event.add_argument('--field')
 event.add_argument('--length')
 event.add_argument('--offset')
 
 # Raw Event Settings
 raw_event = search_subparser.add_parser(
 'rawevent', help='Get the raw event results from a search')
 raw_event.add_argument(
 'row_id', help='Specific row id for the raw event')
 
 # Chart Data Settings
 chart_data = search_subparser.add_parser(
 'chartdata', help='Returns data in a chart format')
 chart_data.add_argument('--field')
 chart_data.add_argument('--length')
 chart_data.add_argument('--offset')
 # Retrieve all arguments
 args = parser.parse_args()
 if args.command is None:
 # Not sure if this one is mandatory
 parser.error('you should provide an action to execute')
 elif args.command == 'search' and args.search_kind is None:
 parser.error(
 "you should provide the kind of search "
 "when performing the 'search' action")
 else:
 return args
def query(arc, args):
 search_id, response = arc.search(
 args.query,
 start_time=args.starttime,
 end_time=args.endtime,
 discover_fields=args.discoverfields,
 summary_fields=args.summaryfields,
 fields_summary=args.fieldssummary,
 local_search=args.localsearch,
 search_type=args.searchtype,
 timeout=args.timeout)
 if args.wait:
 arc.wait(search_id)
 return search_id
def search(arc, search_id, kind, args):
 if kind == 'histogram':
 return arc.histogram(search_id=search_id)
 
 if kind == 'drilldown':
 return arc.drilldown(
 search_id=search_id,
 start_time=args.starttime,
 end_time=args.endtime)
 
 if kind == 'event':
 return arc.events(
 search_id=search_id,
 dir=args.dir,
 fields=args.fields,
 length=args.length,
 offset=args.offset)
 if kind == 'rawevent':
 return arc.raw_events(search_id, row_ids=args.rowids)
 
 if kind == 'chartdata':
 return arc.events(
 search_id=search_id,
 length=args.length,
 offset=args.offset)
 
 if kind == 'status':
 if args.wait:
 arc.wait(search_id)
 return arc.search_complete(search_id=search_id)
if __name__ == '__main__':
 args = parse_command_line()
 # Sets the target Logger Server
 arcsightrest.ArcsightLogger.TARGET = args.target
 arc = arcsightrest.ArcsightLogger(
 args.username,
 args.password,
 args.unsecuressl)
 if args.command == 'query':
 print(query(arc, args))
 elif args.command == 'search':
 print(search(arc, args.search_id, args.search_kind, args))

I changed a bit how the wait parameter is used, as you described it being an option of status. And the fact that, on a query, it should use information from other actions will make the parser a bit more messy. The drawback being that the user can't perform a wait with one command, they will need 2:

$ python script.py <target> <username> <password> query ... --wait
$ python script.py <target> <username> <password> search 12345 rawevent 12

Lastly, please do not use strings as comments, but real comments instead: i.e. lines starting with a #.

lang-py

AltStyle によって変換されたページ (->オリジナル) /