Commit a03dc1eb authored by dominicc@chromium.org's avatar dominicc@chromium.org

Store alerts in sheriff-o-matic's memcache.

TEST=Tools/GardeningServer/tests.py
BUG=401358
R=eseidel@chromium.org, ojan@chromium.org

Review URL: https://codereview.chromium.org/465233002

git-svn-id: svn://svn.chromium.org/blink/trunk@180153 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent bfdd5ed6
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import calendar
import datetime
import json
import webapp2
from google.appengine.api import memcache
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime.datetime):
return calendar.timegm(obj.timetuple())
# Let the base class default method raise the TypeError
return json.JSONEncoder.default(self, obj)
class AlertsHandler(webapp2.RequestHandler):
MEMCACHE_ALERTS_KEY = 'alerts'
def get(self):
self.response.headers.add_header('Access-Control-Allow-Origin', '*')
self.response.headers['Content-Type'] = 'application/json'
alerts = memcache.get(AlertsHandler.MEMCACHE_ALERTS_KEY)
if not alerts:
return
self.response.write(json.dumps(alerts, cls=DateTimeEncoder, indent=1))
def post(self):
try:
alerts = json.loads(self.request.get('content'))
except ValueError:
self.response.set_status(400, 'content field was not JSON')
return
alerts.update({
'date': datetime.datetime.utcnow(),
'alerts': alerts['alerts']
})
memcache.set(AlertsHandler.MEMCACHE_ALERTS_KEY, alerts)
app = webapp2.WSGIApplication([
('/alerts', AlertsHandler)
])
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import alerts
import json
import unittest
import webtest
from google.appengine.api import memcache
from google.appengine.ext import testbed
class AlertsTest(unittest.TestCase):
def setUp(self):
self.testbed = testbed.Testbed()
self.testbed.activate()
self.testbed.init_memcache_stub()
self.testapp = webtest.TestApp(alerts.app)
def tearDown(self):
self.testbed.deactivate()
def check_json_headers(self, res):
self.assertEqual(res.content_type, 'application/json')
# This is necessary for cross-site tools to retrieve alerts
self.assertEqual(res.headers['access-control-allow-origin'], '*')
def test_get_no_data_cached(self):
res = self.testapp.get('/alerts')
self.check_json_headers(res)
self.assertEqual(res.body, '')
def test_happy_path(self):
# Set it.
params = {'content': '{"alerts": ["hello", "world"]}'}
self.testapp.post('/alerts', params)
# Get it.
res = self.testapp.get('/alerts')
self.check_json_headers(res)
alerts = json.loads(res.body)
# The server should have stuck a 'date' on there.
self.assertTrue('date' in alerts)
self.assertEqual(type(alerts['date']), int)
self.assertEqual(alerts['alerts'], ['hello', 'world'])
def test_post_invalid_data_not_reflected(self):
params = {'content': '[{"this is not valid JSON'}
self.testapp.post('/alerts', params, status=400)
res = self.testapp.get('/alerts')
self.assertEqual(res.body, '')
def test_post_invalid_data_does_not_overwrite_valid_data(self):
# Populate the cache with something valid
params = {'content': '{"alerts": "everything is OK"}'}
self.testapp.post('/alerts', params)
self.testapp.post('/alerts', {'content': 'woozlwuzl'}, status=400)
res = self.testapp.get('/alerts')
self.check_json_headers(res)
alerts = json.loads(res.body)
self.assertEqual(alerts['alerts'], 'everything is OK')
...@@ -9,6 +9,9 @@ handlers: ...@@ -9,6 +9,9 @@ handlers:
static_files: sheriff-o-matic.html static_files: sheriff-o-matic.html
upload: sheriff-o-matic.html upload: sheriff-o-matic.html
- url: /alerts
script: alerts.app
- url: /favicon.ico - url: /favicon.ico
static_files: favicon.ico static_files: favicon.ico
upload: favicon.ico upload: favicon.ico
...@@ -40,9 +43,15 @@ skip_files: ...@@ -40,9 +43,15 @@ skip_files:
- ^(.*/)?#.*#$ - ^(.*/)?#.*#$
- ^(.*/)?.*~$ - ^(.*/)?.*~$
- ^(.*/)?.*\.py[co]$ - ^(.*/)?.*\.py[co]$
- ^(.*/)?.*_test\.py$
- ^(.*/)?tests\.py$
- ^(.*/)?.*/RCS/.*$ - ^(.*/)?.*/RCS/.*$
- ^(.*/)?\..*$ - ^(.*/)?\..*$
- ^(.*/)?.*\.md$ - ^(.*/)?.*\.md$
- ^(.*/)?LICENSE$ - ^(.*/)?LICENSE$
- ^(.*/)?README$ - ^(.*/)?README$
- ^(.*/)?Makefile$ - ^(.*/)?Makefile$
\ No newline at end of file
libraries:
- name: webapp2
version: "latest"
#!/usr/bin/env python
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
import unittest
_gae_sdk_not_on_python_path_message = '''
You must include the google_appengine SDK directory on PYTHONPATH.
'''
_webtest_not_installed_message = '''
Could not load webtest python module. You may need to:
sudo apt-get python-webtest
'''
def main():
try:
import dev_appserver
except ImportError:
print >> sys.stderr, _gae_sdk_not_on_python_path_message
raise
dev_appserver.fix_sys_path()
try:
import webtest
except ImportError:
print >> sys.stderr, _webtest_not_installed_message
raise
tests_path = os.path.dirname(sys.modules[__name__].__file__)
suite = unittest.loader.TestLoader().discover(tests_path,
pattern='*_test.py')
unittest.TextTestRunner(verbosity=2).run(suite)
if __name__ == '__main__':
main()
...@@ -67,6 +67,8 @@ found in the LICENSE file. ...@@ -67,6 +67,8 @@ found in the LICENSE file.
update: function() { update: function() {
var annotationPromise = CTFailureGroup.fetchAnnotations(); var annotationPromise = CTFailureGroup.fetchAnnotations();
# FIXME: Change this to http://sheriff-o-matic.appspot.com/alerts
# when Sheriff-o-matic is redeployed to serve /alerts.
net.json('http://auto-sheriff.appspot.com/data').then(function(data) { net.json('http://auto-sheriff.appspot.com/data').then(function(data) {
annotationPromise.then(function(annotations) { annotationPromise.then(function(annotations) {
// FIXME: Don't special-case the blink master. // FIXME: Don't special-case the blink master.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment