RT-Client-Tools/scripts/rt-bulk-send
2018-06-07 08:53:32 -04:00

106 lines
3.3 KiB
Python
Executable file

#!/usr/bin/env python3
import argparse
import logging
import pathlib
import subprocess
import sys
logger = logging.getLogger('rt-bulk-send')
def parse_arguments(arglist):
parser = argparse.ArgumentParser()
action = parser.add_mutually_exclusive_group()
action.add_argument(
'--correspond',
dest='action', action='store_const', const='correspond',
default='correspond',
help="Send correspondence on found tickets (default)",
)
action.add_argument(
'--comment',
dest='action', action='store_const', const='comment',
help="Comment on found tickets",
)
parser.add_argument(
'--loglevel',
choices=['debug', 'info', 'warning', 'error', 'critical'],
default='info',
help="Show log messages at this level (default %(default)s)",
)
parser.add_argument(
'search',
help="TicketSQL search, like you would pass to `rt search`",
)
parser.add_argument(
'body_file',
type=pathlib.Path,
help="Path to file that has the content of your correspondence/comment",
)
parser.add_argument(
'rt_args', metavar='rt arguments',
nargs=argparse.REMAINDER,
help="Additional arguments to pass to `rt correspond/comment`",
)
return parser.parse_args(arglist)
def setup_logger(logger, loglevel, stream):
formatter = logging.Formatter('%(name)s: %(levelname)s: %(message)s')
handler = logging.StreamHandler(stream)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(loglevel)
def act_on_ticket(ticket_id, args, body_file):
body_file.seek(0)
return subprocess.run(
['rt', args.action, *args.rt_args, '-m', '-', ticket_id],
stdin=body_file,
check=True,
)
def main(arglist=None, stdout=sys.stdout, stderr=sys.stderr):
args = parse_arguments(arglist)
setup_logger(logger, getattr(logging, args.loglevel.upper()), stderr)
try:
body_file = args.body_file.open()
except OSError as error:
logger.critical("error opening {}: {}".format(args.body_file, error))
return 3
if not body_file.seekable():
logger.critical("file {} must be seekable".format(args.body_file))
with body_file:
return 3
action_verb = args.action.title()
failures = 0
with body_file, subprocess.Popen(
['rt', 'search', '-i', args.search],
stdout=subprocess.PIPE,
universal_newlines=True,
) as search_pipe:
for line in search_pipe.stdout:
ticket_id = line.rstrip('\n')
if not ticket_id:
continue
logger.info("%sing on %s", action_verb, ticket_id)
try:
act_on_ticket(ticket_id, args, body_file)
except subprocess.CalledProcessError as error:
logger.error("Failed to %s on %s: rt returned exit code %s",
args.action, ticket_id, error.returncode)
failures += 1
if search_pipe.returncode != 0:
logger.critical("`rt search` returned exit code %s", search_pipe.returncode)
return 4
elif failures == 0:
return 0
else:
return min(10 + failures, 99)
if __name__ == '__main__':
exit(main())