[MediaWiki-commits] [Gerrit] wikimedia...process-control[master]: Send failmail

2017-03-20 Thread jenkins-bot (Code Review)
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 000..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 ",
+"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

[MediaWiki-commits] [Gerrit] wikimedia...process-control[master]: Send failmail

2017-03-17 Thread Ejegg (Code Review)
Ejegg has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/343365 )

Change subject: Send failmail
..

Send failmail

Change-Id: I987df527c07e95b5bde31c89118d72681673d94a
TODO: check the send args in tests
---
M job_wrapper.py
M tests/test_job_wrapper.py
2 files changed, 34 insertions(+), 8 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/process-control 
refs/changes/65/343365/1

diff --git a/job_wrapper.py b/job_wrapper.py
index 4813b3a..4a07833 100644
--- a/job_wrapper.py
+++ b/job_wrapper.py
@@ -1,6 +1,8 @@
 from __future__ import print_function
 import datetime
+from email.mime.text import MIMEText
 import shlex
+import smtplib
 import subprocess
 import sys
 import threading
@@ -61,18 +63,39 @@
 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.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)
+data = stderr_data.decode("utf-8")
+print(data, file=sys.stderr)
+self.fail_mail(message, data)
 
 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.fail_mail(message)
 # FIXME: Job will return SIGKILL now, fail_exitcode should ignore that 
signal now?
 
+def fail_mail(self, subject, body="Hope your wits are freshly sharpened!"):
+msg = MIMEText(body)
+# TODO: get these from our global config
+from_address = "Fail Mail "
+to_address = "fr-t...@wikimedia.org"
+
+msg["Subject"] = "Fail Mail : " + subject
+msg["From"] = from_address
+msg["To"] = to_address
+
+mailer = smtplib.SMTP("localhost")
+mailer.sendmail(from_address, to_address, msg.as_string())
+mailer.quit()
+
 def store_job_output(self, stdout_data):
 if "stdout_destination" not in self.config:
 return
diff --git a/tests/test_job_wrapper.py b/tests/test_job_wrapper.py
index 730ca2c..d4ef6dd 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
@@ -22,8 +23,8 @@
 assert captured.stdout == ""
 assert captured.stderr == ""
 
-
-def test_return_code():
+@patch("smtplib.SMTP")
+def test_return_code(MockSmtp):
 with iocapture.capture() as captured:
 run_job("return_code.yaml")
 
@@ -33,7 +34,8 @@
 
 # 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")
 
@@ -44,7 +46,8 @@
 )
 
 
-def test_stderr():
+@patch("smtplib.SMTP")
+def test_stderr(MockSmtp):
 with iocapture.capture() as captured:
 run_job("errors.yaml")
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I987df527c07e95b5bde31c89118d72681673d94a
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/process-control
Gerrit-Branch: master
Gerrit-Owner: Ejegg 

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