jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/343365 )

Change subject: Send failmail
......................................................................


Send failmail

TODO: check the send args in tests

Change-Id: I987df527c07e95b5bde31c89118d72681673d94a
---
M job_wrapper.py
A mailer.py
M test-requirements.txt
M tests/test_job_wrapper.py
4 files changed, 65 insertions(+), 9 deletions(-)

Approvals:
  jenkins-bot: Verified
  Awight: Looks good to me, approved



diff --git a/job_wrapper.py b/job_wrapper.py
index 4813b3a..4c3cae6 100644
--- a/job_wrapper.py
+++ b/job_wrapper.py
@@ -7,7 +7,7 @@
 import yaml
 
 import lock
-
+import mailer
 
 # TODO: Global config.
 DEFAULT_TIMEOUT = 600
@@ -21,6 +21,7 @@
 
         self.name = self.config["name"]
         self.start_time = datetime.datetime.utcnow().isoformat()
+        self.mailer = mailer.Mailer(self.config)
 
         if "timeout" in self.config:
             self.timeout = self.config["timeout"]
@@ -61,16 +62,23 @@
             self.fail_exitcode(return_code)
 
     def fail_exitcode(self, return_code):
-        print("Job {name} failed with code {code}".format(name=self.name, 
code=return_code), file=sys.stderr)
+        message = "Job {name} failed with code {code}".format(name=self.name, 
code=return_code)
+        print(message, file=sys.stderr)
         # TODO: Prevent future jobs according to config.
+        self.mailer.fail_mail(message)
 
     def fail_has_stderr(self, stderr_data):
-        print("Job {name} printed things to stderr:".format(name=self.name), 
file=sys.stderr)
-        print(stderr_data.decode("utf-8"), file=sys.stderr)
+        message = "Job {name} printed things to stderr:".format(name=self.name)
+        print(message, file=sys.stderr)
+        body = stderr_data.decode("utf-8")
+        print(body, file=sys.stderr)
+        self.mailer.fail_mail(message, body)
 
     def fail_timeout(self):
         self.process.kill()
-        print("Job {name} timed out after {timeout} 
seconds".format(name=self.name, timeout=self.timeout), file=sys.stderr)
+        message = "Job {name} timed out after {timeout} 
seconds".format(name=self.name, timeout=self.timeout)
+        print(message, file=sys.stderr)
+        self.mailer.fail_mail(message)
         # FIXME: Job will return SIGKILL now, fail_exitcode should ignore that 
signal now?
 
     def store_job_output(self, stdout_data):
diff --git a/mailer.py b/mailer.py
new file mode 100644
index 0000000..526f750
--- /dev/null
+++ b/mailer.py
@@ -0,0 +1,36 @@
+from email.mime.text import MIMEText
+import smtplib
+
+
+class Mailer(object):
+    def __init__(self, config):
+        # defaults
+        self.config = {
+            "from_address": "Fail Mail <fr-t...@wikimedia.org>",
+            "to_address": "fr-t...@wikimedia.org"
+        }
+        self.config.update(config)
+        # FIXME: this is set to ensure one failmail per instance. Should
+        # do something more sophisticated to collect all calls and send
+        # the mail before exiting.
+        self.sent_fail_mail = False
+
+    def fail_mail(self, subject, body="Hope your wits are freshly sharpened!"):
+        if self.sent_fail_mail:
+            return
+
+        msg = MIMEText(body)
+
+        msg["Subject"] = "Fail Mail : " + subject
+        msg["From"] = self.config["from_address"]
+        msg["To"] = self.config["to_address"]
+
+        mailer = smtplib.SMTP("localhost")
+        mailer.sendmail(
+            self.config["from_address"],
+            self.config["to_address"],
+            msg.as_string()
+        )
+        mailer.quit()
+        # only send one failmail per instance
+        self.sent_fail_mail = True
diff --git a/test-requirements.txt b/test-requirements.txt
index dbff9b7..54d3bb9 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,3 +1,4 @@
 iocapture
+mock
 nose
 pytest
diff --git a/tests/test_job_wrapper.py b/tests/test_job_wrapper.py
index 730ca2c..450a051 100644
--- a/tests/test_job_wrapper.py
+++ b/tests/test_job_wrapper.py
@@ -1,3 +1,4 @@
+from mock import patch
 import iocapture
 import nose
 import os
@@ -23,17 +24,22 @@
         assert captured.stderr == ""
 
 
-def test_return_code():
+@patch("smtplib.SMTP")
+def test_return_code(MockSmtp):
+    expected = "Job False job failed with code 1\n"
     with iocapture.capture() as captured:
         run_job("return_code.yaml")
 
         assert captured.stdout == ""
-        assert captured.stderr == "Job False job failed with code 1\n"
+        assert captured.stderr == expected
+
+    MockSmtp().sendmail.assert_called_once()
 
 
 # Must finish in less than two seconds, i.e. must have timed out.
 @nose.tools.timed(2)
-def test_timeout():
+@patch("smtplib.SMTP")
+def test_timeout(MockSmtp):
     with iocapture.capture() as captured:
         run_job("timeout.yaml")
 
@@ -43,8 +49,11 @@
             "Job Timing out job failed with code -9\n"
         )
 
+    MockSmtp().sendmail.assert_called_once()
 
-def test_stderr():
+
+@patch("smtplib.SMTP")
+def test_stderr(MockSmtp):
     with iocapture.capture() as captured:
         run_job("errors.yaml")
 
@@ -55,6 +64,8 @@
             "Job Bad grep job failed with code 2\n"
         )
 
+    MockSmtp().sendmail.assert_called_once()
+
 
 def test_store_output():
     path = "/tmp/which_out.log"

-- 
To view, visit https://gerrit.wikimedia.org/r/343365
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I987df527c07e95b5bde31c89118d72681673d94a
Gerrit-PatchSet: 7
Gerrit-Project: wikimedia/fundraising/process-control
Gerrit-Branch: master
Gerrit-Owner: Ejegg <eeggles...@wikimedia.org>
Gerrit-Reviewer: Awight <awi...@wikimedia.org>
Gerrit-Reviewer: Cdentinger <cdentin...@wikimedia.org>
Gerrit-Reviewer: Ejegg <eeggles...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to