Complete unit tests for rule base.
This commit is contained in:
parent
1056b8b6d7
commit
684bf3b72e
@ -92,57 +92,36 @@ class InvalidParameter(BileanException):
|
||||
msg_fmt = _("Invalid value '%(value)s' specified for '%(name)s'")
|
||||
|
||||
|
||||
class ClusterNotFound(BileanException):
|
||||
msg_fmt = _("The cluster (%(cluster)s) could not be found.")
|
||||
|
||||
|
||||
class NodeNotFound(BileanException):
|
||||
msg_fmt = _("The node (%(node)s) could not be found.")
|
||||
|
||||
|
||||
class RuleTypeNotFound(BileanException):
|
||||
msg_fmt = _("Rule type (%(rule_type)s) is not found.")
|
||||
|
||||
|
||||
class ProfileTypeNotMatch(BileanException):
|
||||
class RuleTypeNotMatch(BileanException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class ProfileNotFound(BileanException):
|
||||
msg_fmt = _("The profile (%(profile)s) could not be found.")
|
||||
class RuleNotFound(BileanException):
|
||||
msg_fmt = _("The rule (%(rule)s) could not be found.")
|
||||
|
||||
|
||||
class ProfileNotSpecified(BileanException):
|
||||
msg_fmt = _("Profile not specified.")
|
||||
class RuleNotSpecified(BileanException):
|
||||
msg_fmt = _("Rule not specified.")
|
||||
|
||||
|
||||
class ProfileOperationFailed(BileanException):
|
||||
class RuleOperationFailed(BileanException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class ProfileOperationTimeout(BileanException):
|
||||
class RuleOperationTimeout(BileanException):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class PolicyNotSpecified(BileanException):
|
||||
msg_fmt = _("Policy not specified.")
|
||||
|
||||
|
||||
class PolicyTypeNotFound(BileanException):
|
||||
msg_fmt = _("Policy type (%(policy_type)s) is not found.")
|
||||
|
||||
|
||||
class PolicyNotFound(BileanException):
|
||||
msg_fmt = _("The policy (%(policy)s) could not be found.")
|
||||
|
||||
|
||||
class PolicyBindingNotFound(BileanException):
|
||||
msg_fmt = _("The policy (%(policy)s) is not found attached to the "
|
||||
"specified cluster (%(identity)s).")
|
||||
|
||||
|
||||
class PolicyTypeConflict(BileanException):
|
||||
msg_fmt = _("The policy with type (%(policy_type)s) already exists.")
|
||||
class UserNotFound(BileanException):
|
||||
msg_fmt = _("The user (%(user)s) could not be found.")
|
||||
|
||||
|
||||
class InvalidSchemaError(BileanException):
|
||||
@ -176,23 +155,6 @@ class RequestLimitExceeded(BileanException):
|
||||
msg_fmt = _('Request limit exceeded: %(message)s')
|
||||
|
||||
|
||||
class WebhookNotFound(BileanException):
|
||||
msg_fmt = _("The webhook (%(webhook)s) could not be found.")
|
||||
|
||||
|
||||
class ReceiverNotFound(BileanException):
|
||||
msg_fmt = _("The receiver (%(receiver)s) could not be found.")
|
||||
|
||||
|
||||
class ActionNotFound(BileanException):
|
||||
msg_fmt = _("The action (%(action)s) could not be found.")
|
||||
|
||||
|
||||
class ActionInProgress(BileanException):
|
||||
msg_fmt = _("Cluster %(cluster_name)s already has an action (%(action)s) "
|
||||
"in progress.")
|
||||
|
||||
|
||||
class EventNotFound(BileanException):
|
||||
msg_fmt = _("The event (%(event)s) could not be found.")
|
||||
|
||||
@ -227,23 +189,12 @@ class TrustNotFound(InternalError):
|
||||
msg_fmt = _("The trust for trustor (%(trustor)s) could not be found.")
|
||||
|
||||
|
||||
class ResourceCreationFailure(InternalError):
|
||||
# Used when creating resources in other services
|
||||
msg_fmt = _("Failed in creating %(rtype)s.")
|
||||
|
||||
|
||||
class ResourceUpdateFailure(InternalError):
|
||||
# Used when updating resources from other services
|
||||
msg_fmt = _("Failed in updating %(resource)s.")
|
||||
|
||||
|
||||
class ResourceDeletionFailure(InternalError):
|
||||
# Used when deleting resources from other services
|
||||
msg_fmt = _("Failed in deleting %(resource)s.")
|
||||
|
||||
|
||||
class ResourceNotFound(InternalError):
|
||||
# Used when retrieving resources from other services
|
||||
msg_fmt = _("The resource (%(resource)s) could not be found.")
|
||||
|
||||
|
||||
@ -260,11 +211,6 @@ class InvalidSpec(InternalError):
|
||||
msg_fmt = _("%(message)s")
|
||||
|
||||
|
||||
class PolicyNotAttached(InternalError):
|
||||
msg_fmt = _("The policy (%(policy)s) is not attached to the specified "
|
||||
"cluster (%(cluster)s).")
|
||||
|
||||
|
||||
class HTTPExceptionDisguise(Exception):
|
||||
"""Disguises HTTP exceptions.
|
||||
|
||||
|
@ -24,7 +24,6 @@ from sqlalchemy.orm.session import Session
|
||||
|
||||
from bilean.common import consts
|
||||
from bilean.common import exception
|
||||
from bilean.common.i18n import _
|
||||
from bilean.db.sqlalchemy import filters as db_filters
|
||||
from bilean.db.sqlalchemy import migration
|
||||
from bilean.db.sqlalchemy import models
|
||||
@ -133,14 +132,12 @@ def user_get(context, user_id, show_deleted=False, tenant_safe=True):
|
||||
def user_update(context, user_id, values):
|
||||
user = user_get(context, user_id)
|
||||
|
||||
if not user:
|
||||
raise exception.NotFound(_('Attempt to update a user with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': user_id,
|
||||
'msg': 'that does not exist'})
|
||||
if user is None:
|
||||
raise exception.UserNotFound(user=user_id)
|
||||
|
||||
user.update(values)
|
||||
user.save(_session(context))
|
||||
return user
|
||||
|
||||
|
||||
def user_create(context, values):
|
||||
@ -153,11 +150,9 @@ def user_create(context, values):
|
||||
def user_delete(context, user_id):
|
||||
session = _session(context)
|
||||
user = user_get(context, user_id)
|
||||
if not user:
|
||||
raise exception.NotFound(_('Attempt to delete a user with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': user_id,
|
||||
'msg': 'that does not exist'})
|
||||
if user is None:
|
||||
return
|
||||
|
||||
# Delete all related resource records
|
||||
for resource in user.resources:
|
||||
session.delete(resource)
|
||||
@ -196,7 +191,7 @@ def user_get_all(context, show_deleted=False, limit=None,
|
||||
|
||||
def rule_get(context, rule_id, show_deleted=False):
|
||||
query = model_query(context, models.Rule)
|
||||
rule = query.get(rule_id)
|
||||
rule = query.filter_by(id=rule_id).first()
|
||||
|
||||
deleted_ok = show_deleted or context.show_deleted
|
||||
if rule is None or rule.deleted_at is not None and not deleted_ok:
|
||||
@ -239,11 +234,8 @@ def rule_create(context, values):
|
||||
def rule_update(context, rule_id, values):
|
||||
rule = rule_get(context, rule_id)
|
||||
|
||||
if not rule:
|
||||
raise exception.NotFound(_('Attempt to update a rule with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': rule_id,
|
||||
'msg': 'that does not exist'})
|
||||
if rule is None:
|
||||
raise exception.RuleNotFound(rule=rule_id)
|
||||
|
||||
rule.update(values)
|
||||
rule.save(_session(context))
|
||||
@ -252,11 +244,9 @@ def rule_update(context, rule_id, values):
|
||||
def rule_delete(context, rule_id):
|
||||
rule = rule_get(context, rule_id)
|
||||
|
||||
if not rule:
|
||||
raise exception.NotFound(_('Attempt to delete a rule with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': rule_id,
|
||||
'msg': 'that does not exist'})
|
||||
if rule is None:
|
||||
return
|
||||
|
||||
session = Session.object_session(rule)
|
||||
rule.soft_delete(session=session)
|
||||
session.flush()
|
||||
@ -315,11 +305,8 @@ def resource_create(context, values):
|
||||
def resource_update(context, resource_id, values):
|
||||
resource = resource_get(context, resource_id)
|
||||
|
||||
if not resource:
|
||||
raise exception.NotFound(_('Attempt to update a resource with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': resource_id,
|
||||
'msg': 'that does not exist'})
|
||||
if resource is None:
|
||||
raise exception.ResourceNotFound(resource=resource_id)
|
||||
|
||||
resource.update(values)
|
||||
resource.save(_session(context))
|
||||
@ -329,11 +316,9 @@ def resource_update(context, resource_id, values):
|
||||
def resource_delete(context, resource_id, soft_delete=True):
|
||||
resource = resource_get(context, resource_id)
|
||||
|
||||
if not resource:
|
||||
raise exception.NotFound(_('Attempt to delete a resource with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': resource_id,
|
||||
'msg': 'that does not exist'})
|
||||
if resource is None:
|
||||
return
|
||||
|
||||
session = Session.object_session(resource)
|
||||
if soft_delete:
|
||||
resource.soft_delete(session=session)
|
||||
@ -416,10 +401,8 @@ def job_delete(context, job_id):
|
||||
job = model_query(context, models.Job).get(job_id)
|
||||
|
||||
if job is None:
|
||||
raise exception.NotFound(_('Attempt to delete a job with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': job_id,
|
||||
'msg': 'that does not exist'})
|
||||
return
|
||||
|
||||
session = Session.object_session(job)
|
||||
session.delete(job)
|
||||
session.flush()
|
||||
@ -469,11 +452,8 @@ def policy_create(context, values):
|
||||
def policy_update(context, policy_id, values):
|
||||
policy = policy_get(context, policy_id)
|
||||
|
||||
if not policy:
|
||||
raise exception.NotFound(_('Attempt to update a policy with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': policy_id,
|
||||
'msg': 'that does not exist'})
|
||||
if policy is None:
|
||||
raise exception.PolicyNotFound(policy=policy_id)
|
||||
|
||||
policy.update(values)
|
||||
policy.save(_session(context))
|
||||
@ -482,11 +462,9 @@ def policy_update(context, policy_id, values):
|
||||
def policy_delete(context, policy_id):
|
||||
policy = policy_get(context, policy_id)
|
||||
|
||||
if not policy:
|
||||
raise exception.NotFound(_('Attempt to delete a policy with id: '
|
||||
'%(id)s %(msg)s') % {
|
||||
'id': policy_id,
|
||||
'msg': 'that does not exist'})
|
||||
if policy is None:
|
||||
return
|
||||
|
||||
session = Session.object_session(policy)
|
||||
policy.soft_delete(session=session)
|
||||
session.flush()
|
||||
|
@ -14,12 +14,13 @@
|
||||
SQLAlchemy models for Bilean data.
|
||||
"""
|
||||
|
||||
import uuid
|
||||
import six
|
||||
|
||||
from bilean.db.sqlalchemy import types
|
||||
|
||||
from oslo_db.sqlalchemy import models
|
||||
from oslo_utils import timeutils
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
import sqlalchemy
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
@ -28,6 +29,7 @@ from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.orm.session import Session
|
||||
|
||||
BASE = declarative_base()
|
||||
UUID4 = uuidutils.generate_uuid
|
||||
|
||||
|
||||
def get_session():
|
||||
@ -70,7 +72,7 @@ class BileanBase(models.ModelBase):
|
||||
if not session:
|
||||
session = get_session()
|
||||
session.begin()
|
||||
for k, v in values.iteritems():
|
||||
for k, v in six.iteritems(values):
|
||||
setattr(self, k, v)
|
||||
session.commit()
|
||||
|
||||
@ -121,7 +123,7 @@ class Policy(BASE, BileanBase, SoftDelete, models.TimestampMixin):
|
||||
__tablename__ = 'policy'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
default=lambda: UUID4())
|
||||
name = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
rules = sqlalchemy.Column(types.List)
|
||||
is_default = sqlalchemy.Column(sqlalchemy.Boolean, default=False)
|
||||
@ -133,7 +135,7 @@ class Rule(BASE, BileanBase, SoftDelete, models.TimestampMixin):
|
||||
|
||||
__tablename__ = 'rule'
|
||||
id = sqlalchemy.Column(sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
default=lambda: UUID4())
|
||||
name = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
type = sqlalchemy.Column(sqlalchemy.String(255))
|
||||
spec = sqlalchemy.Column(types.Dict)
|
||||
@ -145,7 +147,7 @@ class Resource(BASE, BileanBase, SoftDelete, models.TimestampMixin):
|
||||
|
||||
__tablename__ = 'resource'
|
||||
id = sqlalchemy.Column(sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()))
|
||||
default=lambda: UUID4())
|
||||
user_id = sqlalchemy.Column(
|
||||
sqlalchemy.String(36),
|
||||
sqlalchemy.ForeignKey('user.id'),
|
||||
@ -166,8 +168,7 @@ class Event(BASE, BileanBase, SoftDelete):
|
||||
__tablename__ = 'event'
|
||||
|
||||
id = sqlalchemy.Column(sqlalchemy.String(36), primary_key=True,
|
||||
default=lambda: str(uuid.uuid4()),
|
||||
unique=True)
|
||||
default=lambda: UUID4(), unique=True)
|
||||
user_id = sqlalchemy.Column(sqlalchemy.String(36),
|
||||
sqlalchemy.ForeignKey('user.id'),
|
||||
nullable=False)
|
||||
|
@ -122,15 +122,16 @@ class Rule(object):
|
||||
return cls.from_db_record(rule)
|
||||
|
||||
@classmethod
|
||||
def load_all(cls, context, show_deleted=False, limit=None,
|
||||
marker=None, sort_keys=None, sort_dir=None,
|
||||
filters=None):
|
||||
def load_all(cls, context, limit=None, marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None, show_deleted=False):
|
||||
'''Retrieve all rules from database.'''
|
||||
|
||||
records = db_api.rule_get_all(context, show_deleted=show_deleted,
|
||||
limit=limit, marker=marker,
|
||||
sort_keys=sort_keys, sort_dir=sort_dir,
|
||||
filters=filters)
|
||||
records = db_api.rule_get_all(context, limit=limit,
|
||||
marker=marker,
|
||||
sort_keys=sort_keys,
|
||||
sort_dir=sort_dir,
|
||||
filters=filters,
|
||||
show_deleted=show_deleted)
|
||||
|
||||
return [cls.from_db_record(record) for record in records]
|
||||
|
||||
@ -177,16 +178,6 @@ class Rule(object):
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def do_delete(self, obj):
|
||||
'''For subclass to override.'''
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def do_update(self, obj, new_rule, **params):
|
||||
'''For subclass to override.'''
|
||||
|
||||
return NotImplemented
|
||||
|
||||
def to_dict(self):
|
||||
rule_dict = {
|
||||
'id': self.id,
|
||||
|
@ -11,12 +11,11 @@
|
||||
# under the License.
|
||||
|
||||
import mock
|
||||
from oslo_utils import encodeutils
|
||||
import six
|
||||
|
||||
from bilean.common import exception
|
||||
from bilean.common.i18n import _
|
||||
from bilean.common import schema
|
||||
from bilean.common import utils as common_utils
|
||||
from bilean.db import api as db_api
|
||||
from bilean.engine import environment
|
||||
from bilean.rules import base as rule_base
|
||||
@ -106,3 +105,159 @@ class TestRuleBase(base.BileanTestCase):
|
||||
self.assertRaises(exception.RuleTypeNotFound,
|
||||
rule_base.Rule,
|
||||
'test-rule', bad_spec)
|
||||
|
||||
def test_load(self):
|
||||
rule = self._create_db_rule()
|
||||
result = rule_base.Rule.load(self.context, rule.id)
|
||||
|
||||
self.assertEqual(rule.id, result.id)
|
||||
self.assertEqual(rule.name, result.name)
|
||||
self.assertEqual(rule.type, result.type)
|
||||
self.assertEqual(rule.spec, result.spec)
|
||||
self.assertEqual(rule.meta_data, result.metadata)
|
||||
self.assertEqual({'key1': 'value1', 'key2': 2}, result.properties)
|
||||
|
||||
self.assertEqual(rule.created_at, result.created_at)
|
||||
self.assertEqual(rule.updated_at, result.updated_at)
|
||||
|
||||
def test_load_not_found(self):
|
||||
ex = self.assertRaises(exception.RuleNotFound,
|
||||
rule_base.Rule.load,
|
||||
self.context, 'fake-rule', None)
|
||||
self.assertEqual('The rule (fake-rule) could not be found.',
|
||||
six.text_type(ex))
|
||||
|
||||
ex = self.assertRaises(exception.RuleNotFound,
|
||||
rule_base.Rule.load,
|
||||
self.context, None, None)
|
||||
self.assertEqual('The rule (None) could not be found.',
|
||||
six.text_type(ex))
|
||||
|
||||
def test_load_all(self):
|
||||
result = rule_base.Rule.load_all(self.context)
|
||||
self.assertEqual([], list(result))
|
||||
|
||||
rule1 = self._create_db_rule(name='rule-1', id='ID1')
|
||||
rule2 = self._create_db_rule(name='rule-2', id='ID2')
|
||||
|
||||
result = rule_base.Rule.load_all(self.context)
|
||||
rules = list(result)
|
||||
self.assertEqual(2, len(rules))
|
||||
self.assertEqual(rule1.id, rules[0].id)
|
||||
self.assertEqual(rule2.id, rules[1].id)
|
||||
|
||||
@mock.patch.object(db_api, 'rule_get_all')
|
||||
def test_load_all_with_params(self, mock_get_all):
|
||||
mock_get_all.return_value = []
|
||||
|
||||
res = list(rule_base.Rule.load_all(self.context))
|
||||
self.assertEqual([], res)
|
||||
mock_get_all.assert_called_once_with(self.context, limit=None,
|
||||
marker=None, sort_keys=None,
|
||||
sort_dir=None, filters=None,
|
||||
show_deleted=False)
|
||||
mock_get_all.reset_mock()
|
||||
|
||||
res = list(rule_base.Rule.load_all(self.context, limit=1,
|
||||
marker='MARKER',
|
||||
sort_keys=['K1'],
|
||||
sort_dir='asc',
|
||||
filters={'name': 'fake-name'}))
|
||||
self.assertEqual([], res)
|
||||
mock_get_all.assert_called_once_with(self.context, limit=1,
|
||||
marker='MARKER',
|
||||
sort_keys=['K1'],
|
||||
sort_dir='asc',
|
||||
filters={'name': 'fake-name'},
|
||||
show_deleted=False)
|
||||
|
||||
def test_delete(self):
|
||||
rule = self._create_db_rule()
|
||||
rule_id = rule.id
|
||||
|
||||
res = rule_base.Rule.delete(self.context, rule_id)
|
||||
self.assertIsNone(res)
|
||||
self.assertRaises(exception.RuleNotFound,
|
||||
rule_base.Rule.load,
|
||||
self.context, rule_id, None)
|
||||
|
||||
def test_delete_not_found(self):
|
||||
result = rule_base.Rule.delete(self.context, 'fake-rule')
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_store_for_create(self):
|
||||
rule = self._create_rule('test-rule')
|
||||
self.assertIsNone(rule.id)
|
||||
|
||||
rule_id = rule.store(self.context)
|
||||
self.assertIsNotNone(rule_id)
|
||||
self.assertEqual(rule_id, rule.id)
|
||||
|
||||
result = db_api.rule_get(self.context, rule_id)
|
||||
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual('test-rule', result.name)
|
||||
self.assertEqual(rule_id, result.id)
|
||||
self.assertEqual(rule.type, result.type)
|
||||
self.assertEqual(rule.spec, result.spec)
|
||||
self.assertEqual(rule.metadata, result.meta_data)
|
||||
|
||||
self.assertIsNotNone(result.created_at)
|
||||
self.assertIsNone(result.updated_at)
|
||||
|
||||
def test_store_for_update(self):
|
||||
rule = self._create_rule('test-rule')
|
||||
self.assertIsNone(rule.id)
|
||||
rule_id = rule.store(self.context)
|
||||
self.assertIsNotNone(rule_id)
|
||||
self.assertEqual(rule_id, rule.id)
|
||||
|
||||
rule.name = 'test-rule-1'
|
||||
rule.metadata = {'key': 'value'}
|
||||
|
||||
new_id = rule.store(self.context)
|
||||
self.assertEqual(rule_id, new_id)
|
||||
|
||||
result = db_api.rule_get(self.context, rule_id)
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual('test-rule-1', result.name)
|
||||
self.assertEqual({'key': 'value'}, result.meta_data)
|
||||
self.assertIsNotNone(rule.created_at)
|
||||
self.assertIsNotNone(rule.updated_at)
|
||||
|
||||
def test_to_dict(self):
|
||||
rule = self._create_rule('test-rule')
|
||||
rule_id = rule.store(self.context)
|
||||
self.assertIsNotNone(rule_id)
|
||||
expected = {
|
||||
'id': rule_id,
|
||||
'name': rule.name,
|
||||
'type': rule.type,
|
||||
'spec': rule.spec,
|
||||
'metadata': rule.metadata,
|
||||
'created_at': common_utils.format_time(rule.created_at),
|
||||
'updated_at': None,
|
||||
'deleted_at': None,
|
||||
}
|
||||
|
||||
result = rule_base.Rule.load(self.context, rule_id=rule.id)
|
||||
self.assertEqual(expected, result.to_dict())
|
||||
|
||||
def test_get_schema(self):
|
||||
expected = {
|
||||
'key1': {
|
||||
'default': 'value1',
|
||||
'description': 'First key',
|
||||
'readonly': False,
|
||||
'required': False,
|
||||
'type': 'String'
|
||||
},
|
||||
'key2': {
|
||||
'description': 'Second key',
|
||||
'readonly': False,
|
||||
'required': True,
|
||||
'type': 'Integer'
|
||||
},
|
||||
}
|
||||
res = DummyRule.get_schema()
|
||||
self.assertEqual(expected, res)
|
||||
|
Loading…
Reference in New Issue
Block a user