Add service supervisor
This patch set adds supervisor mechanism for Watcher services to get ability to track states. Partially-Implements: blueprint watcher-service-list Change-Id: Iab1cefb971c79ed27b22b6a5d1bed8698e35f9a4
This commit is contained in:
@@ -37,7 +37,8 @@ class TestV1Root(base.FunctionalTest):
|
||||
not_resources = ('id', 'links', 'media_types')
|
||||
actual_resources = tuple(set(data.keys()) - set(not_resources))
|
||||
expected_resources = ('audit_templates', 'audits', 'actions',
|
||||
'action_plans', 'scoring_engines')
|
||||
'action_plans', 'scoring_engines',
|
||||
'services')
|
||||
self.assertEqual(sorted(expected_resources), sorted(actual_resources))
|
||||
|
||||
self.assertIn({'type': 'application/vnd.openstack.watcher.v1+json',
|
||||
|
||||
173
watcher/tests/api/v1/test_services.py
Normal file
173
watcher/tests/api/v1/test_services.py
Normal file
@@ -0,0 +1,173 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
from six.moves.urllib import parse as urlparse
|
||||
|
||||
from watcher.tests.api import base as api_base
|
||||
from watcher.tests.objects import utils as obj_utils
|
||||
|
||||
|
||||
class TestListService(api_base.FunctionalTest):
|
||||
|
||||
def _assert_service_fields(self, service):
|
||||
service_fields = ['id', 'name', 'host', 'status']
|
||||
for field in service_fields:
|
||||
self.assertIn(field, service)
|
||||
|
||||
def test_one(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
response = self.get_json('/services')
|
||||
self.assertEqual(service.id, response['services'][0]["id"])
|
||||
self._assert_service_fields(response['services'][0])
|
||||
|
||||
def test_get_one_by_id(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
response = self.get_json('/services/%s' % service.id)
|
||||
self.assertEqual(service.id, response["id"])
|
||||
self.assertEqual(service.name, response["name"])
|
||||
self._assert_service_fields(response)
|
||||
|
||||
def test_get_one_by_name(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
response = self.get_json(urlparse.quote(
|
||||
'/services/%s' % service['name']))
|
||||
self.assertEqual(service.id, response['id'])
|
||||
self._assert_service_fields(response)
|
||||
|
||||
def test_get_one_soft_deleted(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
service.soft_delete()
|
||||
response = self.get_json(
|
||||
'/services/%s' % service['id'],
|
||||
headers={'X-Show-Deleted': 'True'})
|
||||
self.assertEqual(service.id, response['id'])
|
||||
self._assert_service_fields(response)
|
||||
|
||||
response = self.get_json(
|
||||
'/services/%s' % service['id'],
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, response.status_int)
|
||||
|
||||
def test_detail(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
response = self.get_json('/services/detail')
|
||||
self.assertEqual(service.id, response['services'][0]["id"])
|
||||
self._assert_service_fields(response['services'][0])
|
||||
for service in response['services']:
|
||||
self.assertTrue(
|
||||
all(val is not None for key, val in service.items()
|
||||
if key in ['id', 'name', 'host', 'status'])
|
||||
)
|
||||
|
||||
def test_detail_against_single(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
response = self.get_json('/services/%s/detail' % service.id,
|
||||
expect_errors=True)
|
||||
self.assertEqual(404, response.status_int)
|
||||
|
||||
def test_many(self):
|
||||
service_list = []
|
||||
for idx in range(1, 6):
|
||||
service = obj_utils.create_test_service(
|
||||
self.context, id=idx, host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(idx))
|
||||
service_list.append(service.id)
|
||||
response = self.get_json('/services')
|
||||
self.assertEqual(5, len(response['services']))
|
||||
for service in response['services']:
|
||||
self.assertTrue(
|
||||
all(val is not None for key, val in service.items()
|
||||
if key in ['id', 'name', 'host', 'status']))
|
||||
|
||||
def test_many_without_soft_deleted(self):
|
||||
service_list = []
|
||||
for id_ in [1, 2, 3]:
|
||||
service = obj_utils.create_test_service(
|
||||
self.context, id=id_, host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(id_))
|
||||
service_list.append(service.id)
|
||||
for id_ in [4, 5]:
|
||||
service = obj_utils.create_test_service(
|
||||
self.context, id=id_, host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(id_))
|
||||
service.soft_delete()
|
||||
response = self.get_json('/services')
|
||||
self.assertEqual(3, len(response['services']))
|
||||
ids = [s['id'] for s in response['services']]
|
||||
self.assertEqual(sorted(service_list), sorted(ids))
|
||||
|
||||
def test_services_collection_links(self):
|
||||
for idx in range(1, 6):
|
||||
obj_utils.create_test_service(
|
||||
self.context, id=idx,
|
||||
host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(idx))
|
||||
response = self.get_json('/services/?limit=2')
|
||||
self.assertEqual(2, len(response['services']))
|
||||
|
||||
def test_services_collection_links_default_limit(self):
|
||||
for idx in range(1, 6):
|
||||
obj_utils.create_test_service(
|
||||
self.context, id=idx,
|
||||
host='CONTROLLER',
|
||||
name='SERVICE_{0}'.format(idx))
|
||||
cfg.CONF.set_override('max_limit', 3, 'api', enforce_type=True)
|
||||
response = self.get_json('/services')
|
||||
self.assertEqual(3, len(response['services']))
|
||||
|
||||
|
||||
class TestServicePolicyEnforcement(api_base.FunctionalTest):
|
||||
|
||||
def _common_policy_check(self, rule, func, *arg, **kwarg):
|
||||
self.policy.set_rules({
|
||||
"admin_api": "(role:admin or role:administrator)",
|
||||
"default": "rule:admin_api",
|
||||
rule: "rule:default"})
|
||||
response = func(*arg, **kwarg)
|
||||
self.assertEqual(403, response.status_int)
|
||||
self.assertEqual('application/json', response.content_type)
|
||||
self.assertTrue(
|
||||
"Policy doesn't allow %s to be performed." % rule,
|
||||
jsonutils.loads(response.json['error_message'])['faultstring'])
|
||||
|
||||
def test_policy_disallow_get_all(self):
|
||||
self._common_policy_check(
|
||||
"service:get_all", self.get_json, '/services',
|
||||
expect_errors=True)
|
||||
|
||||
def test_policy_disallow_get_one(self):
|
||||
service = obj_utils.create_test_service(self.context)
|
||||
self._common_policy_check(
|
||||
"service:get", self.get_json,
|
||||
'/services/%s' % service.id,
|
||||
expect_errors=True)
|
||||
|
||||
def test_policy_disallow_detail(self):
|
||||
self._common_policy_check(
|
||||
"service:detail", self.get_json,
|
||||
'/services/detail',
|
||||
expect_errors=True)
|
||||
|
||||
|
||||
class TestServiceEnforcementWithAdminContext(TestListService,
|
||||
api_base.AdminRoleTest):
|
||||
|
||||
def setUp(self):
|
||||
super(TestServiceEnforcementWithAdminContext, self).setUp()
|
||||
self.policy.set_rules({
|
||||
"admin_api": "(role:admin or role:administrator)",
|
||||
"default": "rule:admin_api",
|
||||
"service:detail": "rule:default",
|
||||
"service:get": "rule:default",
|
||||
"service:get_all": "rule:default"})
|
||||
@@ -17,11 +17,16 @@
|
||||
|
||||
import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
from watcher.common.messaging import messaging_handler
|
||||
from watcher.common import rpc
|
||||
from watcher.common import service
|
||||
from watcher import objects
|
||||
from watcher.tests import base
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
class DummyManager(object):
|
||||
|
||||
@@ -37,6 +42,38 @@ class DummyManager(object):
|
||||
self.status_topic = "status_topic"
|
||||
self.notification_topics = []
|
||||
self.api_version = self.API_VERSION
|
||||
self.service_name = None
|
||||
|
||||
|
||||
class TestServiceHeartbeat(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestServiceHeartbeat, self).setUp()
|
||||
|
||||
@mock.patch.object(objects.Service, 'list')
|
||||
@mock.patch.object(objects.Service, 'create')
|
||||
def test_send_beat_with_creating_service(self, mock_create,
|
||||
mock_list):
|
||||
CONF.set_default('host', 'fake-fqdn')
|
||||
service_heartbeat = service.ServiceHeartbeat(
|
||||
service_name='watcher-service')
|
||||
mock_list.return_value = []
|
||||
service_heartbeat.send_beat()
|
||||
mock_list.assert_called_once_with(mock.ANY,
|
||||
filters={'name': 'watcher-service',
|
||||
'host': 'fake-fqdn'})
|
||||
self.assertEqual(1, mock_create.call_count)
|
||||
|
||||
@mock.patch.object(objects.Service, 'list')
|
||||
@mock.patch.object(objects.Service, 'save')
|
||||
def test_send_beat_without_creating_service(self, mock_save, mock_list):
|
||||
service_heartbeat = service.ServiceHeartbeat(
|
||||
service_name='watcher-service')
|
||||
mock_list.return_value = [objects.Service(mock.Mock(),
|
||||
name='watcher-service',
|
||||
host='controller')]
|
||||
service_heartbeat.send_beat()
|
||||
self.assertEqual(1, mock_save.call_count)
|
||||
|
||||
|
||||
class TestService(base.TestCase):
|
||||
|
||||
303
watcher/tests/db/test_service.py
Normal file
303
watcher/tests/db/test_service.py
Normal file
@@ -0,0 +1,303 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
# Copyright (c) 2016 Servionica
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
"""Tests for manipulating Service via the DB API"""
|
||||
|
||||
import freezegun
|
||||
import six
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from watcher.common import exception
|
||||
from watcher.tests.db import base
|
||||
from watcher.tests.db import utils
|
||||
|
||||
|
||||
class TestDbServiceFilters(base.DbTestCase):
|
||||
|
||||
FAKE_OLDER_DATE = '2014-01-01T09:52:05.219414'
|
||||
FAKE_OLD_DATE = '2015-01-01T09:52:05.219414'
|
||||
FAKE_TODAY = '2016-02-24T09:52:05.219414'
|
||||
|
||||
def setUp(self):
|
||||
super(TestDbServiceFilters, self).setUp()
|
||||
self.context.show_deleted = True
|
||||
self._data_setup()
|
||||
|
||||
def _data_setup(self):
|
||||
service1_name = "SERVICE_ID_1"
|
||||
service2_name = "SERVICE_ID_2"
|
||||
service3_name = "SERVICE_ID_3"
|
||||
|
||||
with freezegun.freeze_time(self.FAKE_TODAY):
|
||||
self.service1 = utils.create_test_service(
|
||||
id=1, name=service1_name, host="controller",
|
||||
last_seen_up=timeutils.parse_isotime("2016-09-22T08:32:05"))
|
||||
with freezegun.freeze_time(self.FAKE_OLD_DATE):
|
||||
self.service2 = utils.create_test_service(
|
||||
id=2, name=service2_name, host="controller",
|
||||
last_seen_up=timeutils.parse_isotime("2016-09-22T08:32:05"))
|
||||
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
|
||||
self.service3 = utils.create_test_service(
|
||||
id=3, name=service3_name, host="controller",
|
||||
last_seen_up=timeutils.parse_isotime("2016-09-22T08:32:05"))
|
||||
|
||||
def _soft_delete_services(self):
|
||||
with freezegun.freeze_time(self.FAKE_TODAY):
|
||||
self.dbapi.soft_delete_service(self.service1.id)
|
||||
with freezegun.freeze_time(self.FAKE_OLD_DATE):
|
||||
self.dbapi.soft_delete_service(self.service2.id)
|
||||
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
|
||||
self.dbapi.soft_delete_service(self.service3.id)
|
||||
|
||||
def _update_services(self):
|
||||
with freezegun.freeze_time(self.FAKE_TODAY):
|
||||
self.dbapi.update_service(
|
||||
self.service1.id, values={"host": "controller1"})
|
||||
with freezegun.freeze_time(self.FAKE_OLD_DATE):
|
||||
self.dbapi.update_service(
|
||||
self.service2.id, values={"host": "controller2"})
|
||||
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
|
||||
self.dbapi.update_service(
|
||||
self.service3.id, values={"host": "controller3"})
|
||||
|
||||
def test_get_service_list_filter_deleted_true(self):
|
||||
with freezegun.freeze_time(self.FAKE_TODAY):
|
||||
self.dbapi.soft_delete_service(self.service1.id)
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted': True})
|
||||
|
||||
self.assertEqual([self.service1['name']], [r.name for r in res])
|
||||
|
||||
def test_get_service_list_filter_deleted_false(self):
|
||||
with freezegun.freeze_time(self.FAKE_TODAY):
|
||||
self.dbapi.soft_delete_service(self.service1.id)
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted': False})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['name'], self.service3['name']]),
|
||||
set([r.name for r in res]))
|
||||
|
||||
def test_get_service_list_filter_deleted_at_eq(self):
|
||||
self._soft_delete_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted_at__eq': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_deleted_at_lt(self):
|
||||
self._soft_delete_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted_at__lt': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_deleted_at_lte(self):
|
||||
self._soft_delete_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted_at__lte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_deleted_at_gt(self):
|
||||
self._soft_delete_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted_at__gt': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_deleted_at_gte(self):
|
||||
self._soft_delete_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'deleted_at__gte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service1['id'], self.service2['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
# created_at #
|
||||
|
||||
def test_get_service_list_filter_created_at_eq(self):
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'created_at__eq': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_created_at_lt(self):
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'created_at__lt': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_created_at_lte(self):
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'created_at__lte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_created_at_gt(self):
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'created_at__gt': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_created_at_gte(self):
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'created_at__gte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service1['id'], self.service2['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
# updated_at #
|
||||
|
||||
def test_get_service_list_filter_updated_at_eq(self):
|
||||
self._update_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'updated_at__eq': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_updated_at_lt(self):
|
||||
self._update_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'updated_at__lt': self.FAKE_TODAY})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_updated_at_lte(self):
|
||||
self._update_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'updated_at__lte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service2['id'], self.service3['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
def test_get_service_list_filter_updated_at_gt(self):
|
||||
self._update_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'updated_at__gt': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual([self.service1['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_list_filter_updated_at_gte(self):
|
||||
self._update_services()
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'updated_at__gte': self.FAKE_OLD_DATE})
|
||||
|
||||
self.assertEqual(
|
||||
set([self.service1['id'], self.service2['id']]),
|
||||
set([r.id for r in res]))
|
||||
|
||||
|
||||
class DbServiceTestCase(base.DbTestCase):
|
||||
|
||||
def _create_test_service(self, **kwargs):
|
||||
service = utils.get_test_service(**kwargs)
|
||||
self.dbapi.create_service(service)
|
||||
return service
|
||||
|
||||
def test_get_service_list(self):
|
||||
ids = []
|
||||
for i in range(1, 6):
|
||||
service = utils.create_test_service(
|
||||
id=i,
|
||||
name="SERVICE_ID_%s" % i,
|
||||
host="controller_{0}".format(i))
|
||||
ids.append(six.text_type(service['id']))
|
||||
res = self.dbapi.get_service_list(self.context)
|
||||
res_ids = [r.id for r in res]
|
||||
self.assertEqual(ids.sort(), res_ids.sort())
|
||||
|
||||
def test_get_service_list_with_filters(self):
|
||||
service1 = self._create_test_service(
|
||||
id=1,
|
||||
name="SERVICE_ID_1",
|
||||
host="controller_1",
|
||||
)
|
||||
service2 = self._create_test_service(
|
||||
id=2,
|
||||
name="SERVICE_ID_2",
|
||||
host="controller_2",
|
||||
)
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'host': 'controller_1'})
|
||||
self.assertEqual([service1['id']], [r.id for r in res])
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context, filters={'host': 'controller_3'})
|
||||
self.assertEqual([], [r.id for r in res])
|
||||
|
||||
res = self.dbapi.get_service_list(
|
||||
self.context,
|
||||
filters={'host': 'controller_2'})
|
||||
self.assertEqual([service2['id']], [r.id for r in res])
|
||||
|
||||
def test_get_service_by_name(self):
|
||||
created_service = self._create_test_service()
|
||||
service = self.dbapi.get_service_by_name(
|
||||
self.context, created_service['name'])
|
||||
self.assertEqual(service.name, created_service['name'])
|
||||
|
||||
def test_get_service_that_does_not_exist(self):
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
self.dbapi.get_service_by_id,
|
||||
self.context, 404)
|
||||
|
||||
def test_update_service(self):
|
||||
service = self._create_test_service()
|
||||
res = self.dbapi.update_service(
|
||||
service['id'], {'host': 'controller_test'})
|
||||
self.assertEqual('controller_test', res.host)
|
||||
|
||||
def test_update_service_that_does_not_exist(self):
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
self.dbapi.update_service,
|
||||
405,
|
||||
{'name': ''})
|
||||
|
||||
def test_create_service_already_exists(self):
|
||||
service_id = "STRATEGY_ID"
|
||||
self._create_test_service(name=service_id)
|
||||
self.assertRaises(exception.ServiceAlreadyExists,
|
||||
self._create_test_service,
|
||||
name=service_id)
|
||||
@@ -12,7 +12,9 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
"""Magnum test utilities."""
|
||||
"""Watcher test utilities."""
|
||||
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from watcher.db import api as db_api
|
||||
|
||||
@@ -212,6 +214,33 @@ def get_test_strategy(**kwargs):
|
||||
}
|
||||
|
||||
|
||||
def get_test_service(**kwargs):
|
||||
return {
|
||||
'id': kwargs.get('id', 1),
|
||||
'name': kwargs.get('name', 'watcher-service'),
|
||||
'host': kwargs.get('host', 'controller'),
|
||||
'last_seen_up': kwargs.get(
|
||||
'last_seen_up',
|
||||
timeutils.parse_isotime('2016-09-22T08:32:06').replace(tzinfo=None)
|
||||
),
|
||||
'created_at': kwargs.get('created_at'),
|
||||
'updated_at': kwargs.get('updated_at'),
|
||||
'deleted_at': kwargs.get('deleted_at'),
|
||||
}
|
||||
|
||||
|
||||
def create_test_service(**kwargs):
|
||||
"""Create test service entry in DB and return Service DB object.
|
||||
|
||||
Function to be used to create test Service objects in the database.
|
||||
:param kwargs: kwargs with overriding values for service's attributes.
|
||||
:returns: Test Service DB object.
|
||||
"""
|
||||
service = get_test_service(**kwargs)
|
||||
dbapi = db_api.get_instance()
|
||||
return dbapi.create_service(service)
|
||||
|
||||
|
||||
def create_test_strategy(**kwargs):
|
||||
"""Create test strategy entry in DB and return Strategy DB object.
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ class FakeManager(object):
|
||||
|
||||
def __init__(self):
|
||||
self.api_version = self.API_VERSION
|
||||
self.service_name = None
|
||||
|
||||
# fake cluster instead on Nova CDM
|
||||
self.fake_cdmc = faker_cluster_state.FakerModelCollector()
|
||||
|
||||
@@ -53,7 +53,11 @@ policy_data = """
|
||||
|
||||
"strategy:detail": "",
|
||||
"strategy:get": "",
|
||||
"strategy:get_all": ""
|
||||
"strategy:get_all": "",
|
||||
|
||||
"service:detail": "",
|
||||
"service:get": "",
|
||||
"service:get_all": ""
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@@ -118,19 +118,29 @@ class TestUtils(test_base.TestCase):
|
||||
def test_datetime_or_none(self):
|
||||
naive_dt = datetime.datetime.now()
|
||||
dt = timeutils.parse_isotime(timeutils.isotime(naive_dt))
|
||||
self.assertEqual(dt, utils.datetime_or_none(dt))
|
||||
self.assertEqual(dt, utils.datetime_or_none(dt, tzinfo_aware=True))
|
||||
self.assertEqual(naive_dt.replace(tzinfo=iso8601.iso8601.Utc(),
|
||||
microsecond=0),
|
||||
utils.datetime_or_none(dt))
|
||||
utils.datetime_or_none(dt, tzinfo_aware=True))
|
||||
self.assertIsNone(utils.datetime_or_none(None))
|
||||
self.assertRaises(ValueError, utils.datetime_or_none, 'foo')
|
||||
|
||||
def test_datetime_or_none_tzinfo_naive(self):
|
||||
naive_dt = datetime.datetime.utcnow()
|
||||
self.assertEqual(naive_dt, utils.datetime_or_none(naive_dt,
|
||||
tzinfo_aware=False))
|
||||
self.assertIsNone(utils.datetime_or_none(None))
|
||||
self.assertRaises(ValueError, utils.datetime_or_none, 'foo')
|
||||
|
||||
def test_datetime_or_str_or_none(self):
|
||||
dts = timeutils.isotime()
|
||||
dt = timeutils.parse_isotime(dts)
|
||||
self.assertEqual(dt, utils.datetime_or_str_or_none(dt))
|
||||
self.assertIsNone(utils.datetime_or_str_or_none(None))
|
||||
self.assertEqual(dt, utils.datetime_or_str_or_none(dts))
|
||||
self.assertEqual(dt, utils.datetime_or_str_or_none(dt,
|
||||
tzinfo_aware=True))
|
||||
self.assertIsNone(utils.datetime_or_str_or_none(None,
|
||||
tzinfo_aware=True))
|
||||
self.assertEqual(dt, utils.datetime_or_str_or_none(dts,
|
||||
tzinfo_aware=True))
|
||||
self.assertRaises(ValueError, utils.datetime_or_str_or_none, 'foo')
|
||||
|
||||
def test_int_or_none(self):
|
||||
|
||||
105
watcher/tests/objects/test_service.py
Normal file
105
watcher/tests/objects/test_service.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# Copyright 2015 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from testtools import matchers
|
||||
|
||||
from watcher import objects
|
||||
from watcher.tests.db import base
|
||||
from watcher.tests.db import utils
|
||||
|
||||
|
||||
class TestServiceObject(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestServiceObject, self).setUp()
|
||||
self.fake_service = utils.get_test_service()
|
||||
|
||||
def test_get_by_id(self):
|
||||
service_id = self.fake_service['id']
|
||||
with mock.patch.object(self.dbapi, 'get_service_by_id',
|
||||
autospec=True) as mock_get_service:
|
||||
mock_get_service.return_value = self.fake_service
|
||||
service = objects.Service.get(self.context, service_id)
|
||||
mock_get_service.assert_called_once_with(self.context,
|
||||
service_id)
|
||||
self.assertEqual(self.context, service._context)
|
||||
|
||||
def test_list(self):
|
||||
with mock.patch.object(self.dbapi, 'get_service_list',
|
||||
autospec=True) as mock_get_list:
|
||||
mock_get_list.return_value = [self.fake_service]
|
||||
services = objects.Service.list(self.context)
|
||||
self.assertEqual(1, mock_get_list.call_count, 1)
|
||||
self.assertThat(services, matchers.HasLength(1))
|
||||
self.assertIsInstance(services[0], objects.Service)
|
||||
self.assertEqual(self.context, services[0]._context)
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(self.dbapi, 'create_service',
|
||||
autospec=True) as mock_create_service:
|
||||
mock_create_service.return_value = self.fake_service
|
||||
service = objects.Service(self.context, **self.fake_service)
|
||||
|
||||
fake_service = utils.get_test_service()
|
||||
|
||||
service.create()
|
||||
mock_create_service.assert_called_once_with(fake_service)
|
||||
self.assertEqual(self.context, service._context)
|
||||
|
||||
def test_save(self):
|
||||
_id = self.fake_service['id']
|
||||
with mock.patch.object(self.dbapi, 'get_service_by_id',
|
||||
autospec=True) as mock_get_service:
|
||||
mock_get_service.return_value = self.fake_service
|
||||
with mock.patch.object(self.dbapi, 'update_service',
|
||||
autospec=True) as mock_update_service:
|
||||
service = objects.Service.get(self.context, _id)
|
||||
service.name = 'UPDATED NAME'
|
||||
service.save()
|
||||
|
||||
mock_get_service.assert_called_once_with(self.context, _id)
|
||||
mock_update_service.assert_called_once_with(
|
||||
_id, {'name': 'UPDATED NAME'})
|
||||
self.assertEqual(self.context, service._context)
|
||||
|
||||
def test_refresh(self):
|
||||
_id = self.fake_service['id']
|
||||
returns = [dict(self.fake_service, name="first name"),
|
||||
dict(self.fake_service, name="second name")]
|
||||
expected = [mock.call(self.context, _id),
|
||||
mock.call(self.context, _id)]
|
||||
with mock.patch.object(self.dbapi, 'get_service_by_id',
|
||||
side_effect=returns,
|
||||
autospec=True) as mock_get_service:
|
||||
service = objects.Service.get(self.context, _id)
|
||||
self.assertEqual("first name", service.name)
|
||||
service.refresh()
|
||||
self.assertEqual("second name", service.name)
|
||||
self.assertEqual(expected, mock_get_service.call_args_list)
|
||||
self.assertEqual(self.context, service._context)
|
||||
|
||||
def test_soft_delete(self):
|
||||
_id = self.fake_service['id']
|
||||
with mock.patch.object(self.dbapi, 'get_service_by_id',
|
||||
autospec=True) as mock_get_service:
|
||||
mock_get_service.return_value = self.fake_service
|
||||
with mock.patch.object(self.dbapi, 'soft_delete_service',
|
||||
autospec=True) as mock_soft_delete:
|
||||
service = objects.Service.get(self.context, _id)
|
||||
service.soft_delete()
|
||||
mock_get_service.assert_called_once_with(self.context, _id)
|
||||
mock_soft_delete.assert_called_once_with(_id)
|
||||
self.assertEqual(self.context, service._context)
|
||||
@@ -178,6 +178,32 @@ def create_test_scoring_engine(context, **kw):
|
||||
return scoring_engine
|
||||
|
||||
|
||||
def get_test_service(context, **kw):
|
||||
"""Return a Service object with appropriate attributes.
|
||||
|
||||
NOTE: The object leaves the attributes marked as changed, such
|
||||
that a create() could be used to commit it to the DB.
|
||||
"""
|
||||
db_service = db_utils.get_test_service(**kw)
|
||||
service = objects.Service(context)
|
||||
for key in db_service:
|
||||
if key == 'last_seen_up':
|
||||
db_service[key] = None
|
||||
setattr(service, key, db_service[key])
|
||||
return service
|
||||
|
||||
|
||||
def create_test_service(context, **kw):
|
||||
"""Create and return a test service object.
|
||||
|
||||
Create a service in the DB and return a Service object with
|
||||
appropriate attributes.
|
||||
"""
|
||||
service = get_test_service(context, **kw)
|
||||
service.create()
|
||||
return service
|
||||
|
||||
|
||||
def get_test_strategy(context, **kw):
|
||||
"""Return a Strategy object with appropriate attributes.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user