Refactor: Have run_as catch the four known cases and relay as a unified CommandException
diff --git a/occ.py b/occ.py
index e1a2b3b..2b97835 100644
--- a/occ.py
+++ b/occ.py
@@ -22,7 +22,6 @@
import subprocess
import socket
import pwd
-import sys
import os
import getpass
@@ -36,9 +35,24 @@
"""
+class CommandException(Exception):
+ reason: str
+ exitcode: int
+
+ def __init__(self, reason, exitcode=0):
+ self.reason = reason
+ self.exitcode = exitcode
+
+
def run_as(username=getpass.getuser(), args=()):
""" Run a command as a specific user """
- pw_record = pwd.getpwnam(username)
+ if not args:
+ return # Nothing to do? boooo
+ try:
+ pw_record = pwd.getpwnam(username)
+ except KeyError:
+ print("Could not execute command as %s - user not found??" % username)
+ raise CommandException("Subprocess error - could not run command as non-existent user %s" % username, 7)
user_name = pw_record.pw_name
user_uid = pw_record.pw_uid
user_gid = pw_record.pw_gid
@@ -48,14 +62,25 @@
env['PWD'] = os.getcwd()
env['USER'] = username
print("Running command %s as user %s..." % (" ".join(args), username))
- process = subprocess.Popen(
- args, preexec_fn=change_user(user_uid, user_gid), cwd=os.getcwd(), env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- )
- result = process.communicate(timeout=30)
+ try:
+ process = subprocess.Popen(
+ args, preexec_fn=change_user(user_uid, user_gid), cwd=os.getcwd(), env=env, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+ )
+ result = process.communicate(timeout=30)
+ except FileNotFoundError:
+ print("Could not find script or executable to run, %s" % args[0])
+ raise CommandException("Could not find executable '%s'" % args[0], 1)
+ except subprocess.TimeoutExpired:
+ print("Execution timed out")
+ raise CommandException("Subprocess error - execution of command timed out", 2)
+ except subprocess.SubprocessError:
+ print("Subprocess error - likely could not change to user %s" % username)
+ raise CommandException("Subprocess error - unable to change to user %s for running command (permission denied?)" % username, 7)
if process.returncode == 0:
return
else:
- raise subprocess.CalledProcessError(returncode=process.returncode, cmd=args, output=result[0].decode('utf-8'))
+ print("on-commit command failed with exit code %d!" % process.returncode)
+ raise CommandException(result[0].decode('utf-8'), process.returncode)
def change_user(user_uid, user_gid):
@@ -91,25 +116,12 @@
try:
run_as(runas, (oncommit,))
print("Command executed successfully")
- except subprocess.CalledProcessError as e:
- print("on-commit command failed with exit code %d!" % e.returncode)
+ except CommandException as e:
+ print("on-commit command failed with exit code %d!" % e.exitcode)
if blamelist:
print("Sending error details to %s" % blamelist)
- asfpy.messaging.mail(recipient=blamelist, subject=blamesubject, message=TMPL_FAILURE % (e.returncode, e.output))
- except FileNotFoundError:
- print("Could not find script to execute; file not found!")
- if blamelist:
- print("Sending error details to %s" % blamelist)
- asfpy.messaging.mail(recipient=blamelist, subject=blamesubject,
- message=TMPL_FAILURE % (-1, "Script file %s not found" % oncommit))
- except KeyError:
- print("Could not execute command as %s - user not found??" % runas)
- asfpy.messaging.mail(recipient=blamelist, subject=blamesubject,
- message=TMPL_FAILURE % (-1, "Username %s not found" % runas))
- except subprocess.SubprocessError:
- print("Subprocess error - likely could not change to user %s" % runas)
- asfpy.messaging.mail(recipient=blamelist, subject=blamesubject,
- message=TMPL_FAILURE % (-1, "Subprocess error while trying to run as user %s" % runas))
+ asfpy.messaging.mail(recipient=blamelist, subject=blamesubject, message=TMPL_FAILURE % (e.exitcode, e.reason))
+
def main():
print("Loading occ.yaml")