aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilo Casagrande <milo.casagrande@linaro.org>2015-03-09 10:17:05 +0100
committerMilo Casagrande <milo.casagrande@linaro.org>2015-03-09 10:17:05 +0100
commit29b49b434ab2df60fd422616d6c8a2b0248bb311 (patch)
tree9d716f8201b3f21688843a5e645ece2b86740410
parent7e5d4a29da65b9bda84ec249db82a8053547ba02 (diff)
Remove references to subscription handlers.
* We do not use nor plan to implement the subscription mechanism, at least for now.
-rw-r--r--app/handlers/subscription.py95
-rw-r--r--app/handlers/tests/test_subscription_handler.py172
-rw-r--r--app/models/subscription.py181
-rw-r--r--app/models/tests/test_subscription_model.py107
-rw-r--r--app/tests/__init__.py1
-rw-r--r--app/urls.py7
-rw-r--r--app/utils/subscription.py120
7 files changed, 0 insertions, 683 deletions
diff --git a/app/handlers/subscription.py b/app/handlers/subscription.py
deleted file mode 100644
index a6bd578..0000000
--- a/app/handlers/subscription.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright (C) 2014 Linaro Ltd.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""The RequetHandler for /subscription URLs."""
-
-try:
- import simplejson as json
-except ImportError:
- import json
-
-from handlers.base import BaseHandler
-from handlers.response import HandlerResponse
-from handlers.common import SUBSCRIPTION_VALID_KEYS
-from models import (
- EMAIL_KEY,
- SUBSCRIPTION_COLLECTION,
-)
-from utils.subscription import (
- subscribe,
- unsubscribe,
-)
-from utils.validator import is_valid_json
-from utils.db import delete
-
-
-class SubscriptionHandler(BaseHandler):
- """Handle the /subscription URLs."""
-
- def __init__(self, application, request, **kwargs):
- super(SubscriptionHandler, self).__init__(
- application, request, **kwargs
- )
-
- @property
- def collection(self):
- return self.db[SUBSCRIPTION_COLLECTION]
-
- @staticmethod
- def _valid_keys(method):
- return SUBSCRIPTION_VALID_KEYS.get(method, None)
-
- def _post(self, *args, **kwargs):
- response = HandlerResponse()
-
- response.status_code = subscribe(self.db, kwargs['json_obj'])
- response.result = None
- response.reason = self._get_status_message(response.status_code)
-
- return response
-
- def _delete(self, doc_id):
- response = HandlerResponse()
- response.result = None
-
- if self.request.body:
- try:
- json_obj = json.loads(self.request.body.decode('utf8'))
-
- valid, reason = is_valid_json(
- json_obj, self._valid_keys('DELETE')
- )
-
- if valid:
- response.status_code = unsubscribe(
- self.collection, doc_id, json_obj[EMAIL_KEY]
- )
- response.reason = self._get_status_message(
- response.status_code
- )
- else:
- response.status_code = 400
- response.reason = reason
- except ValueError:
- response.status_code = 420
- response.reason = "No JSON data found in the DELETE request"
- else:
- response.status_code = delete(self.collection, doc_id)
- if response.status_code == 200:
- response.reason = (
- "Subscriptsions for resource %s deleted" % doc_id
- )
-
- return response
diff --git a/app/handlers/tests/test_subscription_handler.py b/app/handlers/tests/test_subscription_handler.py
deleted file mode 100644
index bdfaa76..0000000
--- a/app/handlers/tests/test_subscription_handler.py
+++ /dev/null
@@ -1,172 +0,0 @@
-# Copyright (C) 2014 Linaro Ltd.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""Test module for the DefConfHandler handler.."""
-
-import json
-import mongomock
-
-from concurrent.futures import ThreadPoolExecutor
-from mock import (
- MagicMock,
- patch,
-)
-from tornado import (
- ioloop,
- testing,
- web,
-)
-
-from handlers.app import AppHandler
-from urls import _SUBSCRIPTION_URL
-
-# Default Content-Type header returned by Tornado.
-DEFAULT_CONTENT_TYPE = 'application/json; charset=UTF-8'
-
-
-class TestSubscriptionHandler(
- testing.AsyncHTTPTestCase, testing.LogTrapTestCase):
-
- def setUp(self):
- self.mongodb_client = mongomock.Connection()
-
- super(TestSubscriptionHandler, self).setUp()
-
- patched_find_token = patch("handlers.base.BaseHandler._find_token")
- self.find_token = patched_find_token.start()
- self.find_token.return_value = "token"
-
- patched_validate_token = patch("handlers.base.validate_token")
- self.validate_token = patched_validate_token.start()
- self.validate_token.return_value = True
-
- self.addCleanup(patched_find_token.stop)
- self.addCleanup(patched_validate_token.stop)
-
- def get_app(self):
- dboptions = {
- 'dbpassword': "",
- 'dbuser': ""
- }
-
- settings = {
- 'dboptions': dboptions,
- 'client': self.mongodb_client,
- 'executor': ThreadPoolExecutor(max_workers=2),
- 'default_handler_class': AppHandler,
- 'debug': False,
- }
-
- return web.Application([_SUBSCRIPTION_URL], **settings)
-
- def get_new_ioloop(self):
- return ioloop.IOLoop.instance()
-
- @patch('utils.db.find')
- @patch('utils.db.count')
- def test_get(self, mock_count, mock_find):
- mock_count.return_value = 0
- mock_find.return_value = []
-
- expected_body = (
- '{"count": 0, "code": 200, "limit": 0, "result": []}'
- )
-
- headers = {'Authorization': 'foo'}
- response = self.fetch('/subscription', headers=headers)
-
- self.assertEqual(response.code, 200)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
- self.assertEqual(response.body, expected_body)
-
- @patch('handlers.subscription.SubscriptionHandler.collection')
- def test_get_by_id_not_found(self, mock_collection):
- mock_collection.find_one = MagicMock()
- mock_collection.find_one.return_value = None
-
- headers = {'Authorization': 'foo'}
- response = self.fetch('/subscription/sub', headers=headers)
-
- self.assertEqual(response.code, 404)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
-
- def test_post_without_token(self):
-
- body = json.dumps(dict(job='job', kernel='kernel'))
-
- response = self.fetch('/subscription', method='POST', body=body)
-
- self.assertEqual(response.code, 403)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
-
- def test_post_not_json(self):
- headers = {'Authorization': 'foo'}
-
- response = self.fetch(
- '/subscription', method='POST', body='', headers=headers
- )
-
- self.assertEqual(response.code, 415)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
-
- @patch('utils.subscription.find_one')
- def test_post_valid(self, mock_find_one):
- mock_find_one.return_value = dict(_id='sub', job_id='job', emails=[])
-
- headers = {'Authorization': 'foo', 'Content-Type': 'application/json'}
-
- body = json.dumps(dict(job='job', email='email'))
-
- response = self.fetch(
- '/subscription', method='POST', body=body, headers=headers
- )
-
- self.assertEqual(response.code, 201)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
-
- @patch('utils.subscription.find_one')
- def test_delete_valid_with_payload(self, mock_find_one):
- mock_find_one.return_value = dict(
- _id='sub', emails=['email'], job_id='job'
- )
-
- headers = {'Authorization': 'foo', 'Content-Type': 'application/json'}
-
- body = json.dumps(dict(email='email'))
-
- response = self.fetch(
- '/subscription/sub', method='DELETE', body=body,
- headers=headers, allow_nonstandard_methods=True,
- )
-
- self.assertEqual(response.code, 200)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
-
- def test_delete_valid_without_payload(self):
- headers = {'Authorization': 'foo'}
-
- response = self.fetch(
- '/subscription/sub', method='DELETE', headers=headers,
- )
-
- self.assertEqual(response.code, 200)
- self.assertEqual(
- response.headers['Content-Type'], DEFAULT_CONTENT_TYPE)
diff --git a/app/models/subscription.py b/app/models/subscription.py
deleted file mode 100644
index b63182c..0000000
--- a/app/models/subscription.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""
-The model that represents a subscription document in the mongodb collection.
-"""
-
-import types
-
-import models
-import models.base as modb
-
-
-class SubscriptionDocument(modb.BaseDocument):
- """This class represents a subscription document in the mongodb database.
-
- A subscription document contains a list of emails that shoule be notified.
- It contains an external ID that points to the job ID.
- """
-
- def __init__(self, job, kernel):
- doc_name = {
- models.JOB_KEY: job,
- models.KERNEL_KEY: kernel
- }
- self._name = models.SUBSCRIPTION_DOCUMENT_NAME % doc_name
- self._created_on = None
- self._id = None
- self._job_id = None
- self._job = job
- self._kernel = kernel
- self._emails = []
- self._version = None
-
- @property
- def collection(self):
- return models.SUBSCRIPTION_COLLECTION
-
- @property
- def name(self):
- """The name of the object."""
- return self._name
-
- @name.setter
- def name(self, value):
- """Set the name of the document."""
- self._name = value
-
- @property
- def id(self):
- """The ID of this object as returned by mongodb."""
- return self._id
-
- @id.setter
- def id(self, value):
- """Set the ID of this object with the ObjectID from mongodb.
-
- :param value: The ID of this object.
- :type value: str
- """
- self._id = value
-
- @property
- def job(self):
- """The real job name as found on the file system."""
- return self._job
-
- @property
- def kernel(self):
- """The real kernel name as found on the file system."""
- return self._kernel
-
- @property
- def created_on(self):
- """When this object was created."""
- return self._created_on
-
- @created_on.setter
- def created_on(self, value):
- """Set the creation date of this object.
-
- :param value: The lab creation date, in UTC time zone.
- :type value: datetime
- """
- self._created_on = value
-
- @property
- def job_id(self):
- """The job ID this subscriptions belong to."""
- return self._job_id
-
- @job_id.setter
- def job_id(self, value):
- """Set the ID of the associated job."""
- self._job_id = value
-
- @property
- def emails(self):
- """The list of emails subscribed."""
- return self._emails
-
- @emails.setter
- def emails(self, value):
- """Set the emails subscribed."""
- if not isinstance(value, types.ListType):
- if isinstance(value, types.StringTypes):
- value = [value]
- else:
- value = list(value)
-
- self._emails.extend(value)
- # Make sure the list is unique.
- self._emails = list(set(self._emails))
-
- @property
- def version(self):
- """The schema version of this object."""
- return self._version
-
- @version.setter
- def version(self, value):
- """Set the schema version of this object.
-
- :param value: The schema string.
- :type param: str
- """
- self._version = value
-
- def to_dict(self):
- sub_dict = {
- models.CREATED_KEY: self.created_on,
- models.EMAIL_LIST_KEY: self.emails,
- models.JOB_ID_KEY: self.job_id,
- models.JOB_KEY: self.job,
- models.KERNEL_KEY: self.kernel,
- models.NAME_KEY: self.name,
- models.VERSION_KEY: self.version,
- }
-
- if self.id:
- sub_dict[models.ID_KEY] = self.id
-
- return sub_dict
-
- @staticmethod
- def from_json(json_obj):
- """Build a document from a JSON object.
-
- :param json_obj: The JSON object to start from.
- :return An instance of `SubscriptionDocument`.
- """
- sub_doc = None
- if isinstance(json_obj, types.DictionaryType):
- json_pop = json_obj.pop
- job = json_pop(models.JOB_KEY)
- kernel = json_pop(models.KERNEL_KEY)
- doc_id = json_pop(models.ID_KEY)
- # Remove the name key.
- json_pop(models.NAME_KEY)
-
- sub_doc = SubscriptionDocument(job, kernel)
- sub_doc.id = doc_id
- sub_doc.version = json_pop(models.VERSION_KEY, "1.0")
-
- for key, value in json_obj.iteritems():
- try:
- setattr(sub_doc, key, value)
- except AttributeError:
- print key
-
- return sub_doc
diff --git a/app/models/tests/test_subscription_model.py b/app/models/tests/test_subscription_model.py
deleted file mode 100644
index 2b5a6b9..0000000
--- a/app/models/tests/test_subscription_model.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-import types
-import unittest
-
-from bson import json_util
-
-import models.base as modb
-import models.subscription as mods
-
-
-class TestSubscriptionModel(unittest.TestCase):
-
- def test_subscription_document_emails_attribute(self):
- sub_doc = mods.SubscriptionDocument("job", "kernel")
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertItemsEqual([], sub_doc.emails)
-
- def test_subscription_document_emails_attribute_set(self):
- sub_doc = mods.SubscriptionDocument("job", "kernel")
-
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertNotIsInstance(sub_doc.emails, types.StringTypes)
-
- def test_subscription_document_emails_extended(self):
- sub_doc = mods.SubscriptionDocument("job", "kernel")
- sub_doc.emails = "email2"
-
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertEquals(["email2"], sub_doc.emails)
-
- def test_subscription_document_emails_setter_str(self):
- sub_doc = mods.SubscriptionDocument("job", "kernel")
- sub_doc.emails = "an_email"
-
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertEqual(["an_email"], sub_doc.emails)
-
- def test_subscription_document_emails_setter_tuple(self):
- sub_doc = mods.SubscriptionDocument("sub", "job")
- sub_doc.emails = ("an_email", "another_email")
-
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertEqual(["an_email", "another_email"], sub_doc.emails)
-
- def test_subscription_document_to_dict(self):
- expected = {
- "job": "job",
- "kernel": "kernel",
- "name": "sub-job-kernel",
- "emails": [],
- "job_id": None,
- "created_on": None,
- "version": None,
- }
- sub_doc = mods.SubscriptionDocument("job", "kernel")
-
- self.assertEqual(expected, sub_doc.to_dict())
-
- def test_subscription_document_from_json(self):
- json_obj = {
- "_id": "id",
- "name": "sub-job-kernel",
- "job": "job",
- "kernel": "kernel",
- "emails": [],
- "job_id": "job-id",
- "cerated_on": "now"
- }
-
- sub_doc = mods.SubscriptionDocument.from_json(json_obj)
-
- self.assertIsInstance(sub_doc, mods.SubscriptionDocument)
- self.assertIsInstance(sub_doc, modb.BaseDocument)
-
- self.assertEqual(sub_doc.name, 'sub-job-kernel')
- self.assertEqual(sub_doc.job_id, 'job-id')
- self.assertIsInstance(sub_doc.emails, types.ListType)
-
- def test_subscription_document_from_json_with_emails(self):
- json_obj = {
- "_id": "id",
- "job_id": "job-id",
- "name": "sub-job-kernel",
- "job": "job",
- "kernel": "kernel",
- "created_on": None,
- "emails": [
- "a@example.org", "b@example.org"
- ]
- }
-
- sub_doc = mods.SubscriptionDocument.from_json(json_obj)
-
- self.assertIsInstance(sub_doc.emails, types.ListType)
- self.assertEqual(len(sub_doc.emails), 2)
diff --git a/app/tests/__init__.py b/app/tests/__init__.py
index 67cb946..a47fb03 100644
--- a/app/tests/__init__.py
+++ b/app/tests/__init__.py
@@ -41,7 +41,6 @@ def test_modules():
"models.tests.test_job_model",
"models.tests.test_lab_model",
"models.tests.test_report_model",
- "models.tests.test_subscription_model",
"models.tests.test_test_suite_model",
"models.tests.test_token_model",
"utils.batch.tests.test_batch_common",
diff --git a/app/urls.py b/app/urls.py
index c06d228..043d63c 100644
--- a/app/urls.py
+++ b/app/urls.py
@@ -24,7 +24,6 @@ import handlers.job
import handlers.lab
import handlers.report
import handlers.send
-import handlers.subscription
import handlers.test_suite
import handlers.token
import handlers.upload
@@ -39,11 +38,6 @@ _DEFCONF_URL = tornado.web.url(
handlers.defconf.DefConfHandler,
name="defconf"
)
-_SUBSCRIPTION_URL = tornado.web.url(
- r"/subscription[s]?/?(?P<id>.*)",
- handlers.subscription.SubscriptionHandler,
- name="subscription",
-)
_BOOT_URL = tornado.web.url(
r"/boot[s]?/?(?P<id>.*)", handlers.boot.BootHandler, name="boot"
)
@@ -96,7 +90,6 @@ APP_URLS = [
_DEFCONF_URL,
_JOB_URL,
_LAB_URL,
- _SUBSCRIPTION_URL,
_TOKEN_URL,
_VERSION_URL,
_REPORT_URL,
diff --git a/app/utils/subscription.py b/app/utils/subscription.py
deleted file mode 100644
index 83e1903..0000000
--- a/app/utils/subscription.py
+++ /dev/null
@@ -1,120 +0,0 @@
-# Copyright (C) 2014 Linaro Ltd.
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-"""Collection of utilities to handle subscriptions."""
-
-import pymongo
-
-import models
-import models.subscription as mods
-from utils import LOG
-from utils.db import (
- find_one,
- save,
- update,
-)
-
-
-def subscribe(database, json_obj):
- """Subscribe an email to a job.
-
- It accepts a dict-like object that should contain at least the `job_id' and
- `email' keys. All other keys will not be considered.
-
- At the moment no validation is run on the email provided.
-
- :param database: The database where to store the data.
- :param json_obj: A dict-like object with `job_id' and `email' fields.
- :return This function return 201 when the subscription has been performed,
- 404 if the job to subscribe to does not exist, or 500 in case of
- an internal database error.
- """
- ret_val = 404
-
- job = json_obj['job']
- emails = json_obj['email']
-
- job_doc = find_one(database[models.JOB_COLLECTION], job)
- if job_doc:
- job_id = job_doc[models.ID_KEY]
- subscription = find_one(
- database[models.SUBSCRIPTION_COLLECTION],
- job_id,
- 'job_id'
- )
-
- if subscription:
- sub_obj = mods.SubscriptionDocument.from_json(subscription)
- sub_obj.emails = emails
- else:
- sub_id = (
- models.SUBSCRIPTION_DOCUMENT_NAME % job_id
- )
- sub_obj = mods.SubscriptionDocument(sub_id, job_id)
- sub_obj.emails = emails
-
- ret_val = save(database, sub_obj)
-
- return ret_val
-
-
-def unsubscribe(collection, doc_id, email):
- """Unsubscribe an email from a job.
-
- :param collection: The collection where operation will be performed.
- :param doc_id: The job ID from which the email should be unsubscribed.
- :type str
- :param email: The email to unsubscribe.
- :type str
- :return 200 on success, 400 if there is an error removing an email, 500
- in case of a database error.
- """
- ret_val = 400
-
- subscription = find_one(collection, doc_id)
-
- if subscription:
- emails = subscription['emails']
- try:
- emails.remove(email)
- ret_val = update(
- collection, {'_id': doc_id}, {'emails': emails}
- )
- except ValueError, ex:
- LOG.error(
- "Error removing email address from subscription with "
- "'_id': %s" % (doc_id)
- )
- LOG.exception(str(ex))
-
- return ret_val
-
-
-def send(job_id):
- """Send emails to the subscribers.
-
- :param job_id: The job ID for which to send notifications.
- """
- # TODO: add logic to make sure we can send the notifications.
- # We should store the job status.
- database = pymongo.MongoClient()[models.DB_NAME]
-
- subscription = find_one(
- database[models.SUBSCRIPTION_COLLECTION], job_id, 'job_id'
- )
-
- if subscription:
- emails = subscription['emails']
- LOG.info("Sending emails to: %s" % (str(emails)))