def create_store_alert_object(self):

        # First create and store an Alert-Search object
        # Second, use that AlertSearch to foreign-key into an Alert

        search_obj = AlertSearch()
        search_obj.save()

        new_alert = Alert(owner='core',
                          created='2015-09-01T13:20:30+03:00',
                          msg_title='Alert : openstack syslog errors',
                          msg_body='There are 23 incidents of syslog errors',
                          query_id=search_obj.pk)
        new_alert.save()
예제 #2
0
    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()
예제 #3
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.basic_post_body = {
            'name': 'basic test test alert def',
            'search': SavedSearch.objects.all()[0].uuid
        }
예제 #4
0
def check_for_pending_alerts():
    """
     Run an AlertSearch query to check for any pending alerts to be fired.
    """

    saved_alerts = AlertSearch.objects.all()

    for obj in saved_alerts:
        # execute the search, and assuming no error, update the last_ times
        s, start, end = obj.search_recent()
        response = s.execute()
        obj.last_start = start
        obj.last_end = end
        obj.save()

        if response.hits.total > 0:
            # We have a non-zero match for pending alerts
            # Go ahead and generate an instance of the alert object here.
            # We can directly call the producer class to send an email

            msg_dict = obj.build_alert_template(hits=response.hits.total)

            # For this scheduled celery task, pick up the message template
            # from the query object and pass it along. For all other
            # cases, user is allowed to send custom msg_title and msg_body
            alert_obj = Alert(query=obj, msg_title=msg_dict['title'],
                              msg_body=msg_dict['body'])
            alert_obj.save()

            # Filter by fk = AlertSearch obj
            # dont throw an exception from this loop and keep retrying
            # till all the producers in the list are exhausted
            producer_rv_list = list()
            for producer in EmailProducer.objects.filter(query=obj):
                try:
                    producer_ret = producer.send(alert_obj)
                    ret_dict = {producer.query.name: producer_ret}
                except Exception as e:
                    ret_dict = {producer.query.name: e}
                    # Uncomment the lines below if we ever want to mark
                    # this task to be in retry state. For now, we don't
                    # mind that this task is marked success/failure.
                    # check_for_pending_alerts.retry(throw=False)
                    # raise RetryTaskError(None, None)
                producer_rv_list.append(ret_dict)

            return producer_rv_list
예제 #5
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me', receiver='you',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            "sender": "bell@localhost",
            "receiver": "watson@localhost",
            "alert_def": self.alert_def.uuid
        }
예제 #6
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me@localhost',
                                      receiver='you@localhost',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            'sender': '*****@*****.**',
            'receiver': '*****@*****.**',
            'alert_def': self.alert_def.uuid
        }
예제 #7
0
    def test_inner_send_mail_function(self):

        as_obj = AlertSearch()
        as_obj.save()
        new_alert = Alert(owner='core',
                          created='2015-09-01T13:20:30+03:00',
                          msg_title='Alert : openstack syslog errors',
                          msg_body='There are 23 incidents of syslog errors',
                          query_id=as_obj.pk)
        new_alert.save()
        with mock.patch("django.core.mail.send_mail") \
                as sm_mock:
                sm_mock.return_value = 1

                producer_inst = EmailProducer(query=as_obj,
                                              sender='*****@*****.**',
                                              receiver='*****@*****.**')
                producer_inst.save()
                rv = producer_inst.send(new_alert)
                self.assertEqual(rv, sm_mock.return_value)

        as_obj.delete()
        new_alert.delete()
예제 #8
0
    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.basic_post_body = {
            'name': 'basic test test alert def',
            'alert_def': self.alert_def.uuid
        }
예제 #9
0
    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()
예제 #10
0
class AlertViewTests(APITestCase):
    """ Test Alert API """

    fixtures = ['core_initial_data.yaml']

    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.basic_post_body = {
            'name': 'basic test test alert def',
            'alert_def': self.alert_def.uuid
        }

    def test_not_logged_in(self):
        """All operations should fail when not logged in."""

        # Try getting resource with no token.
        response = self.client.get(ALERT_URL)

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try getting resource a bogus token.
        response = self.client.get(
            ALERT_URL,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with no token.
        response = self.client.post(ALERT_URL,
                                    json.dumps(self.basic_post_body),
                                    content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with a bogus token.
        response = self.client.post(
            ALERT_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with no token.
        response = self.client.put(
            ALERT_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with a bogus token.
        response = self.client.put(
            ALERT_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

    def test_post_not_allowed(self):
        """POST operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.post(
            ALERT_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        # pylint: disable=E1101
        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_get(self):
        """GET operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # We should have at least one result in our list, but could have more
        response = self.client.get(
            ALERT_URL,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('count', content)
        self.assertIn('next', content)
        self.assertIn('previous', content)
        self.assertIn('results', content)
        self.assertIsInstance(content['results'], list)
        self.assertGreater(len(content['results']), 0)

        # test the structure of the one we loaded

        response = self.client.get(
            ALERT_URL + "%s/" % self.alert.uuid,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('uuid', content)
        self.assertIn('alert_def', content)
        self.assertIn('created', content)
        self.assertIn('updated', content)
        self.assertIn('short_message', content)
        self.assertIn('long_message', content)

    def test_delete_not_allowed(self):
        """DELETE operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.delete(
            ALERT_URL + '%s/' % self.alert_def.uuid,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_put_not_allowed(self):
        """PUT operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            ALERT_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_patch_not_allowed(self):
        """PATCH operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            ALERT_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)
예제 #11
0
class ModelTests(TestCase):
    """ Test EmailProducer class model"""

    fixtures = ['core_initial_data.yaml']

    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test', long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

    def assertWithinASecond(self, datetime1, datetime2):
        ts1 = arrow.get(datetime1).timestamp / 1000.0
        ts2 = arrow.get(datetime2).timestamp / 1000.0
        self.assertAlmostEqual(ts1, ts2, places=0)

    def test_producer_superclass_raises(self):
        """ Calling send on the Producer superclass should raise an exception
        """

        with self.assertRaises(NotImplementedError):
            super(EmailProducer, self.producer).produce(self.alert)

    # @patch("django.core.mail.send_mail")
    @patch('goldstone.core.models.send_mail')
    def test_producer_produce(self, mock_send_mail):
        """ The return value from send_mail will be the number of successfully
        delivered messages (which can be 0 or 1 since it can only send one
        message).  It could also raise a SMTPException.

        Produce should just pass those through to the caller.
        """

        mock_send_mail.return_value = 1
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 1)
        self.assertEqual(rv, 1)

        mock_send_mail.return_value = 0
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 2)
        self.assertEqual(rv, 0)

        mock_send_mail.side_effect = SMTPException
        with self.assertRaises(SMTPException):
            self.producer.produce(self.alert)
            self.assertEqual(mock_send_mail.call_count, 3)

    def test_search(self):
        """The search method of a SavedSearch should return an ES search"""

        search = self.saved_search.search()
        self.assertIsInstance(search, Search)

    def test_search_recent(self):
        """The search_recent method of a SavedSearch should return an ES search
        a start datetime, and an end datetime.  The initial start datetime
        should be roughly the creation time of the object, and the initial end
        datetime should be roughly the creation time of the object.

        After a call to update_recent_search_window, the last_start and
        last_end dates should be adjusted to reflect the previous search_recent
        call.

        The search will a range clause on the SavedSearch.timestamp_field with
        a start of the last_end and an end of approximately now.

        Finally, if the SavedSearch.timestamp_field is None a search that is
        the same as the result of search() will be returned along with Nones
        for start and end.
        """

        #
        # first pass we should have initialized start/end times
        #
        search, start1, end1 = self.saved_search.search_recent()
        self.assertIsInstance(search, Search)
        self.assertIsInstance(start1, datetime)
        self.assertIsInstance(end1, datetime)
        self.assertWithinASecond(start1, end1)

        def find_range_dict(a, z):
            """Helper function that extracts the dict with range key."""
            if 'range' in z \
                    and self.saved_search.timestamp_field in z['range']:
                return z
            else:
                return a

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'],
                            None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        self.saved_search.update_recent_search_window(start1, end1)

        #
        # let's get the persisted version of our object and test that
        # update_recent_search_window updated the last_start and last_end
        # fields of the object.
        #
        self.saved_search = SavedSearch.objects.get(
            uuid=self.saved_search.uuid)

        self.assertEqual(self.saved_search.last_start, start1)
        self.assertEqual(self.saved_search.last_end, end1)

        #
        # finally, let's run recent_search again and make sure we get updated
        # times.
        #
        search, start2, end2 = self.saved_search.search_recent()
        self.assertIsInstance(start2, datetime)
        self.assertIsInstance(end2, datetime)
        self.assertTrue(start2 == end1)
        self.assertTrue(start2 <= end2)

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'],
                            None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        # doctype should not be set in the search if the SavedSearch doesn't
        # have one, and the result of search_recent() should be the same as
        # that of search() if there is no timestamp_field set.
        self.saved_search.timestamp_field = None
        self.saved_search.doc_type = None

        search = self.saved_search.search()
        search_recent = self.saved_search.search_recent()
        self.assertDictEqual(search.to_dict(), search_recent.to_dict())
        self.assertEqual(search._doc_type, [])

    @patch('goldstone.core.models.Alert')
    def test_alert_def_evaluate(self, mock_alert):
        """tests that alert definitions properly create alerts, and produce
        notifications."""

        # mock out a search_result to trigger the alert condition
        hit_count = 99
        search, start, end = self.saved_search.search_recent()
        search_result = {'hits': {'total': hit_count}}
        self.alert_def.evaluate(search_result, start, end)
        self.assertTrue(mock_alert.called)

        # should be called with *args and **kwargs
        self.assertEqual(len(mock_alert.call_args), 2)

        # interested in kwargs
        expected_short = 'Alert: \'%s\' triggered at %s' % \
            (self.alert_def.name, end)

        expected_long = 'There were %d instances of \'%s\' from ' \
                        '%s to %s.\nAlert Definition: %s' % \
                        (hit_count, self.alert_def.name,
                         start, end, self.alert_def.uuid)

        self.assertIs(mock_alert.call_args[1]['alert_def'], self.alert_def)
        self.assertEqual(mock_alert.call_args[1]['short_message'],
                         expected_short)
        self.assertEqual(mock_alert.call_args[1]['long_message'],
                         expected_long)
예제 #12
0
class ModelTests(TestCase):
    """ Test EmailProducer class model"""

    fixtures = ['core_initial_data.yaml']

    def setUp(self):

        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.producer = EmailProducer(sender='goldstone',
                                      receiver='someone-else',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

    def assertWithinASecond(self, datetime1, datetime2):
        ts1 = arrow.get(datetime1).timestamp / 1000.0
        ts2 = arrow.get(datetime2).timestamp / 1000.0
        self.assertAlmostEqual(ts1, ts2, places=0)

    def test_producer_superclass_raises(self):
        """ Calling send on the Producer superclass should raise an exception
        """

        with self.assertRaises(NotImplementedError):
            super(EmailProducer, self.producer).produce(self.alert)

    # @patch("django.core.mail.send_mail")
    @patch('goldstone.core.models.send_mail')
    def test_producer_produce(self, mock_send_mail):
        """ The return value from send_mail will be the number of successfully
        delivered messages (which can be 0 or 1 since it can only send one
        message).  It could also raise a SMTPException.

        Produce should just pass those through to the caller.
        """

        mock_send_mail.return_value = 1
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 1)
        self.assertEqual(rv, 1)

        mock_send_mail.return_value = 0
        rv = self.producer.produce(self.alert)
        self.assertEqual(mock_send_mail.call_count, 2)
        self.assertEqual(rv, 0)

        mock_send_mail.side_effect = SMTPException
        with self.assertRaises(SMTPException):
            self.producer.produce(self.alert)
            self.assertEqual(mock_send_mail.call_count, 3)

    def test_search(self):
        """The search method of a SavedSearch should return an ES search"""

        search = self.saved_search.search()
        self.assertIsInstance(search, Search)

    def test_search_recent(self):
        """The search_recent method of a SavedSearch should return an ES search
        a start datetime, and an end datetime.  The initial start datetime
        should be roughly the creation time of the object, and the initial end
        datetime should be roughly the creation time of the object.

        After a call to update_recent_search_window, the last_start and
        last_end dates should be adjusted to reflect the previous search_recent
        call.

        The search will a range clause on the SavedSearch.timestamp_field with
        a start of the last_end and an end of approximately now.

        Finally, if the SavedSearch.timestamp_field is None a search that is
        the same as the result of search() will be returned along with Nones
        for start and end.
        """

        #
        # first pass we should have initialized start/end times
        #
        search, start1, end1 = self.saved_search.search_recent()
        self.assertIsInstance(search, Search)
        self.assertIsInstance(start1, datetime)
        self.assertIsInstance(end1, datetime)
        self.assertWithinASecond(start1, end1)

        def find_range_dict(a, z):
            """Helper function that extracts the dict with range key."""
            if 'range' in z \
                    and self.saved_search.timestamp_field in z['range']:
                return z
            else:
                return a

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'], None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end1.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        self.saved_search.update_recent_search_window(start1, end1)

        #
        # let's get the persisted version of our object and test that
        # update_recent_search_window updated the last_start and last_end
        # fields of the object.
        #
        self.saved_search = SavedSearch.objects.get(
            uuid=self.saved_search.uuid)

        self.assertEqual(self.saved_search.last_start, start1)
        self.assertEqual(self.saved_search.last_end, end1)

        #
        # finally, let's run recent_search again and make sure we get updated
        # times.
        #
        search, start2, end2 = self.saved_search.search_recent()
        self.assertIsInstance(start2, datetime)
        self.assertIsInstance(end2, datetime)
        self.assertTrue(start2 == end1)
        self.assertTrue(start2 <= end2)

        range_dict = reduce(lambda a, z: find_range_dict(a, z),
                            search.to_dict()['query']['bool']['must'], None)

        # validate that the range block was added to the search
        self.assertIsNotNone(range_dict)

        # and that it has the expected start and end times
        self.assertDictContainsSubset(
            {'gte': start2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])
        self.assertDictContainsSubset(
            {'lt': end2.isoformat()},
            range_dict['range'][self.saved_search.timestamp_field])

        # doctype should not be set in the search if the SavedSearch doesn't
        # have one, and the result of search_recent() should be the same as
        # that of search() if there is no timestamp_field set.
        self.saved_search.timestamp_field = None
        self.saved_search.doc_type = None

        search = self.saved_search.search()
        search_recent = self.saved_search.search_recent()
        self.assertDictEqual(search.to_dict(), search_recent.to_dict())
        self.assertEqual(search._doc_type, [])

    @patch('goldstone.core.models.Alert')
    def test_alert_def_evaluate(self, mock_alert):
        """tests that alert definitions properly create alerts, and produce
        notifications."""

        # mock out a search_result to trigger the alert condition
        hit_count = 99
        search, start, end = self.saved_search.search_recent()
        search_result = {'hits': {'total': hit_count}}
        self.alert_def.evaluate(search_result, start, end)
        self.assertTrue(mock_alert.called)

        # should be called with *args and **kwargs
        self.assertEqual(len(mock_alert.call_args), 2)

        # interested in kwargs
        expected_short = 'Alert: \'%s\' triggered at %s' % \
            (self.alert_def.name, end)

        expected_long = 'There were %d instances of \'%s\' from ' \
                        '%s to %s.\nAlert Definition: %s' % \
                        (hit_count, self.alert_def.name,
                         start, end, self.alert_def.uuid)

        self.assertIs(mock_alert.call_args[1]['alert_def'], self.alert_def)
        self.assertEqual(mock_alert.call_args[1]['short_message'],
                         expected_short)
        self.assertEqual(mock_alert.call_args[1]['long_message'],
                         expected_long)
예제 #13
0
class AlertDefinitionViewTests(APITestCase):
    """ Test AlertDefitions API """

    fixtures = ['core_initial_data.yaml']

    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.basic_post_body = {
            'name': 'basic test test alert def',
            'search': SavedSearch.objects.all()[0].uuid
        }

    def test_not_logged_in(self):
        """All operations should fail when not logged in."""

        # Try getting resource with no token.
        response = self.client.get(ALERT_DEF_URL)

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try getting resource a bogus token.
        response = self.client.get(
            ALERT_DEF_URL,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with no token.
        response = self.client.post(ALERT_DEF_URL,
                                    json.dumps(self.basic_post_body),
                                    content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with a bogus token.
        response = self.client.post(
            ALERT_DEF_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with no token.
        response = self.client.put(
            ALERT_DEF_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with a bogus token.
        response = self.client.put(
            ALERT_DEF_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

    def test_post_not_allowed(self):
        """POST operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.post(
            ALERT_DEF_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        # pylint: disable=E1101
        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_get(self):
        """GET operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # We should have at least one result in our list, but could have more
        response = self.client.get(
            ALERT_DEF_URL,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('count', content)
        self.assertIn('next', content)
        self.assertIn('previous', content)
        self.assertIn('results', content)
        self.assertIsInstance(content['results'], list)
        self.assertGreater(len(content['results']), 0)

        # test the structure of the one we loaded

        response = self.client.get(
            ALERT_DEF_URL + "%s/" % self.alert_def.uuid,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('uuid', content)
        self.assertIn('name', content)
        self.assertIn('description', content)
        self.assertIn('search', content)
        self.assertIn('created', content)
        self.assertIn('updated', content)
        self.assertIn('enabled', content)
        self.assertIn('short_template', content)
        self.assertIn('long_template', content)

    def test_delete_not_allowed(self):
        """DELETE operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.delete(
            ALERT_DEF_URL + '%s/' % self.alert_def.uuid,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_put_not_allowed(self):
        """PUT operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            ALERT_DEF_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)

    def test_patch_not_allowed(self):
        """PATCH operation tests"""
        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.put(
            ALERT_DEF_URL + '%s/' % self.alert_def.uuid,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_405_METHOD_NOT_ALLOWED)
예제 #14
0
class EmailProducerViewTests(APITestCase):
    """ Test Email Producer API """

    fixtures = ['core_initial_data.yaml']

    def setUp(self):
        self.saved_search = SavedSearch.objects.all()[0]

        self.alert_def = AlertDefinition(name='alert_def',
                                         search=self.saved_search)
        self.alert_def.save()

        self.alert = Alert(short_message='test',
                           long_message='test123',
                           alert_def=self.alert_def)
        self.alert.save()

        self.producer = EmailProducer(sender='me', receiver='you',
                                      alert_def=self.alert_def)
        self.producer.save()

        self.basic_post_body = {
            "sender": "bell@localhost",
            "receiver": "watson@localhost",
            "alert_def": self.alert_def.uuid
        }

    def test_not_logged_in(self):
        """All operations should fail when not logged in."""

        # Try getting resource with no token.
        response = self.client.get(EMAIL_PRODUCER_URL)

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try getting resource a bogus token.
        response = self.client.get(
            EMAIL_PRODUCER_URL,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with no token.
        response = self.client.post(EMAIL_PRODUCER_URL,
                                    json.dumps(self.basic_post_body),
                                    content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try creating resource with a bogus token.
        response = self.client.post(
            EMAIL_PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with no token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json")

        self.assertContains(response,
                            CONTENT_NO_CREDENTIALS,
                            status_code=status.HTTP_401_UNAUTHORIZED)

        # Try updating resource with a bogus token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + self.alert_def.uuid + '/',
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % BAD_TOKEN)

        self.assertContains(response,
                            CONTENT_BAD_TOKEN,
                            status_code=status.HTTP_401_UNAUTHORIZED)

    def test_crud(self):
        """POST operation tests"""

        # Create a user and get the authorization token. Then do the test.
        token = create_and_login()

        # Try creating resource with a valid token.
        response = self.client.post(
            EMAIL_PRODUCER_URL,
            json.dumps(self.basic_post_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_201_CREATED)

        # Quick test of a filtered GET of the new resource
        response = self.client.get(
            EMAIL_PRODUCER_URL + "?sender=bell@localhost",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)

        self.assertIn('count', content)
        self.assertIn('next', content)
        self.assertIn('previous', content)
        self.assertIn('results', content)
        self.assertIsInstance(content['results'], list)
        self.assertGreater(len(content['results']), 0)

        self.bell_uuid = content['results'][0]['uuid']

        # test the structure of the record we posted

        response = self.client.get(
            EMAIL_PRODUCER_URL + "%s/" % self.bell_uuid,
            accept="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        content = json.loads(response.content)
        self.assertIn('uuid', content)
        self.assertIn('alert_def', content)
        self.assertIn('created', content)
        self.assertIn('updated', content)
        self.assertIn('sender', content)
        self.assertIn('receiver', content)
        self.assertEqual(content['sender'], 'bell@localhost')
        self.assertEqual(content['receiver'], 'watson@localhost')
        self.bell_content = content

        put_body = self.bell_content
        put_body['receiver'] = 'howell@localhost'

        # Try updating resource with a valid token.
        response = self.client.put(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            json.dumps(put_body),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_200_OK)

        # Try patching resource with a valid token.
        response = self.client.patch(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            json.dumps({'receiver': 'watson@localhost'}),
            content_type="application/json",
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_200_OK)

        # Try deleting resource with a valid token.
        response = self.client.delete(
            EMAIL_PRODUCER_URL + '%s/' % self.bell_uuid,
            HTTP_AUTHORIZATION=AUTHORIZATION_PAYLOAD % token)

        self.assertEqual(response.status_code,
                         status.HTTP_204_NO_CONTENT)