| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """A common base class for pages that are used to edit configs.""" | 5 """A common base class for pages that are used to edit configs.""" |
| 6 | 6 |
| 7 import json |
| 8 |
| 9 from google.appengine.api import app_identity |
| 10 from google.appengine.api import mail |
| 7 from google.appengine.api import taskqueue | 11 from google.appengine.api import taskqueue |
| 12 from google.appengine.api import users |
| 8 | 13 |
| 9 from dashboard import list_tests | 14 from dashboard import list_tests |
| 10 from dashboard.common import request_handler | 15 from dashboard.common import request_handler |
| 11 from dashboard.common import utils | 16 from dashboard.common import utils |
| 12 from dashboard.common import xsrf | 17 from dashboard.common import xsrf |
| 13 | 18 |
| 14 # Max number of entities to put in one request to /put_entities_task. | 19 # Max number of entities to put in one request to /put_entities_task. |
| 15 _MAX_TESTS_TO_PUT_AT_ONCE = 25 | 20 _MAX_TESTS_TO_PUT_AT_ONCE = 25 |
| 16 | 21 |
| 17 # The queue to use to re-put tests. Should be present in queue.yaml. | 22 # The queue to use to re-put tests. Should be present in queue.yaml. |
| 18 _TASK_QUEUE_NAME = 'edit-sheriffs-queue' | 23 _TASK_QUEUE_NAME = 'edit-sheriffs-queue' |
| 19 | 24 |
| 20 # Minimum time before starting tasks, in seconds. It appears that the tasks | 25 # Minimum time before starting tasks, in seconds. It appears that the tasks |
| 21 # may be executed before the sheriff is saved, so this is a workaround for that. | 26 # may be executed before the sheriff is saved, so this is a workaround for that. |
| 22 # See http://crbug.com/621499 | 27 # See http://crbug.com/621499 |
| 23 _TASK_QUEUE_COUNTDOWN = 60 | 28 _TASK_QUEUE_COUNTDOWN = 60 |
| 24 | 29 |
| 30 _NOTIFICATION_EMAIL_BODY = """ |
| 31 The configuration of %(hostname)s was changed by %(user)s. |
| 32 |
| 33 Key: %(key)s |
| 34 |
| 35 Added test paths: |
| 36 %(added_test_paths)s |
| 37 |
| 38 Removed test paths: |
| 39 %(removed_test_paths)s |
| 40 """ |
| 41 |
| 42 # TODO(qyearsley): Make this customizable by storing the value in datastore. |
| 43 # Make sure to send a notification to both old and new address if this value |
| 44 # gets changed. |
| 45 _NOTIFICATION_ADDRESS = 'chrome-performance-monitoring-alerts@google.com' |
| 46 _SENDER_ADDRESS = 'gasper-alerts@google.com' |
| 47 |
| 25 | 48 |
| 26 class EditConfigHandler(request_handler.RequestHandler): | 49 class EditConfigHandler(request_handler.RequestHandler): |
| 27 """Base class for handlers that are used to add or edit entities. | 50 """Base class for handlers that are used to add or edit entities. |
| 28 | 51 |
| 29 Specifically, this is a common base class for EditSheriffsHandler | 52 Specifically, this is a common base class for EditSheriffsHandler |
| 30 and EditAnomalyConfigsHandler. Both of these kinds of entities | 53 and EditAnomalyConfigsHandler. Both of these kinds of entities |
| 31 represent a configuration that can apply to a set of tests, where | 54 represent a configuration that can apply to a set of tests, where |
| 32 the set of tests is specified with a list of test path patterns. | 55 the set of tests is specified with a list of test path patterns. |
| 33 """ | 56 """ |
| 34 | 57 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 def _UpdateAndReportResults(self, entity): | 120 def _UpdateAndReportResults(self, entity): |
| 98 """Updates the entity and reports the results of this updating.""" | 121 """Updates the entity and reports the results of this updating.""" |
| 99 new_patterns = _SplitPatternLines(self.request.get('patterns')) | 122 new_patterns = _SplitPatternLines(self.request.get('patterns')) |
| 100 old_patterns = entity.patterns | 123 old_patterns = entity.patterns |
| 101 entity.patterns = new_patterns | 124 entity.patterns = new_patterns |
| 102 self._UpdateFromRequestParameters(entity) | 125 self._UpdateFromRequestParameters(entity) |
| 103 entity.put() | 126 entity.put() |
| 104 added_test_paths, removed_test_paths = _ChangeTestPatterns( | 127 added_test_paths, removed_test_paths = _ChangeTestPatterns( |
| 105 old_patterns, new_patterns) | 128 old_patterns, new_patterns) |
| 106 self._RenderResults(entity, added_test_paths, removed_test_paths) | 129 self._RenderResults(entity, added_test_paths, removed_test_paths) |
| 130 self._SendNotificationEmail(entity, added_test_paths, removed_test_paths) |
| 131 |
| 132 def _SendNotificationEmail( |
| 133 self, entity, added_test_paths, removed_test_paths): |
| 134 user_email = users.get_current_user().email() |
| 135 subject = 'Added or updated %s: %s by %s' % ( |
| 136 self._model_class.__name__, entity.key.string_id(), user_email) |
| 137 email_body = _NOTIFICATION_EMAIL_BODY % { |
| 138 'key': entity.key.string_id(), |
| 139 'added_test_paths': json.dumps( |
| 140 list(added_test_paths), indent=2, sort_keys=True, |
| 141 separators=(',', ': ')), |
| 142 'removed_test_paths': json.dumps( |
| 143 list(removed_test_paths), indent=2, sort_keys=True, |
| 144 separators=(',', ': ')), |
| 145 'hostname': app_identity.get_default_version_hostname(), |
| 146 'user': user_email, |
| 147 } |
| 148 mail.send_mail( |
| 149 sender=_SENDER_ADDRESS, |
| 150 to=_NOTIFICATION_ADDRESS, |
| 151 subject=subject, |
| 152 body=email_body) |
| 107 | 153 |
| 108 def _UpdateFromRequestParameters(self, entity): | 154 def _UpdateFromRequestParameters(self, entity): |
| 109 """Updates the given entity based on query parameters. | 155 """Updates the given entity based on query parameters. |
| 110 | 156 |
| 111 This method does not need to put() the entity. | 157 This method does not need to put() the entity. |
| 112 | 158 |
| 113 Args: | 159 Args: |
| 114 entity: The entity to update. | 160 entity: The entity to update. |
| 115 """ | 161 """ |
| 116 raise NotImplementedError() | 162 raise NotImplementedError() |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 test_paths: List of test paths of tests to be re-put. | 273 test_paths: List of test paths of tests to be re-put. |
| 228 """ | 274 """ |
| 229 for start_index in range(0, len(test_paths), _MAX_TESTS_TO_PUT_AT_ONCE): | 275 for start_index in range(0, len(test_paths), _MAX_TESTS_TO_PUT_AT_ONCE): |
| 230 group = test_paths[start_index:start_index + _MAX_TESTS_TO_PUT_AT_ONCE] | 276 group = test_paths[start_index:start_index + _MAX_TESTS_TO_PUT_AT_ONCE] |
| 231 urlsafe_keys = [utils.TestKey(t).urlsafe() for t in group] | 277 urlsafe_keys = [utils.TestKey(t).urlsafe() for t in group] |
| 232 taskqueue.add( | 278 taskqueue.add( |
| 233 url='/put_entities_task', | 279 url='/put_entities_task', |
| 234 params={'keys': ','.join(urlsafe_keys)}, | 280 params={'keys': ','.join(urlsafe_keys)}, |
| 235 queue_name=_TASK_QUEUE_NAME, | 281 queue_name=_TASK_QUEUE_NAME, |
| 236 countdown=_TASK_QUEUE_COUNTDOWN) | 282 countdown=_TASK_QUEUE_COUNTDOWN) |
| OLD | NEW |