Added Goal model into Watcher DB

In this changeset, I added the Goal model into Watcher.
This implies a change into the Watcher DB schema

Partially Implements: blueprint get-goal-from-strategy

Change-Id: I5b5b0ffc7cff8affb59f17743e1af0e1277c2878
This commit is contained in:
Vincent Françoise
2016-03-23 17:01:46 +01:00
parent 91951f3b01
commit be9058f3e3
6 changed files with 665 additions and 40 deletions

View File

@@ -166,6 +166,14 @@ class InvalidUuidOrName(Invalid):
msg_fmt = _("Expected a logical name or uuid but received %(name)s")
class GoalNotFound(ResourceNotFound):
msg_fmt = _("Goal %(goal)s could not be found")
class GoalAlreadyExists(Conflict):
msg_fmt = _("A goal with UUID %(uuid)s already exists")
class AuditTemplateNotFound(ResourceNotFound):
msg_fmt = _("AuditTemplate %(audit_template)s could not be found")

View File

@@ -34,6 +34,102 @@ def get_instance():
class BaseConnection(object):
"""Base class for storage system connections."""
@abc.abstractmethod
def get_goal_list(self, context, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
"""Get specific columns for matching goals.
Return a list of the specified columns for all goals that
match the specified filters.
:param context: The security context
:param filters: Filters to apply. Defaults to None.
:param limit: Maximum number of goals to return.
:param marker: the last item of the previous page; we return the next
result set.
:param sort_key: Attribute by which results should be sorted.
:param sort_dir: direction in which results should be sorted.
(asc, desc)
:returns: A list of tuples of the specified columns.
"""
@abc.abstractmethod
def create_goal(self, values):
"""Create a new goal.
:param values: A dict containing several items used to identify
and track the goal. For example:
::
{
'uuid': utils.generate_uuid(),
'name': 'DUMMY',
'display_name': 'Dummy',
}
:returns: A goal
:raises: :py:class:`~.GoalAlreadyExists`
"""
@abc.abstractmethod
def get_goal_by_id(self, context, goal_id):
"""Return a goal given its ID.
:param context: The security context
:param goal_id: The ID of a goal
:returns: A goal
:raises: :py:class:`~.GoalNotFound`
"""
@abc.abstractmethod
def get_goal_by_uuid(self, context, goal_uuid):
"""Return a goal given its UUID.
:param context: The security context
:param goal_uuid: The UUID of a goal
:returns: A goal
:raises: :py:class:`~.GoalNotFound`
"""
@abc.abstractmethod
def get_goal_by_name(self, context, goal_name):
"""Return a goal given its name.
:param context: The security context
:param goal_name: The name of a goal
:returns: A goal
:raises: :py:class:`~.GoalNotFound`
"""
@abc.abstractmethod
def destroy_goal(self, goal_uuid):
"""Destroy a goal.
:param goal_uuid: The UUID of a goal
:raises: :py:class:`~.GoalNotFound`
"""
@abc.abstractmethod
def update_goal(self, goal_uuid, values):
"""Update properties of a goal.
:param goal_uuid: The UUID of a goal
:param values: A dict containing several items used to identify
and track the goal. For example:
::
{
'uuid': utils.generate_uuid(),
'name': 'DUMMY',
'display_name': 'Dummy',
}
:returns: A goal
:raises: :py:class:`~.GoalNotFound`
:raises: :py:class:`~.Invalid`
"""
@abc.abstractmethod
def get_audit_template_list(self, context, columns=None, filters=None,
limit=None, marker=None, sort_key=None,
@@ -75,7 +171,7 @@ class BaseConnection(object):
'extra': {'automatic': True}
}
:returns: An audit template.
:raises: AuditTemplateAlreadyExists
:raises: :py:class:`~.AuditTemplateAlreadyExists`
"""
@abc.abstractmethod
@@ -85,7 +181,7 @@ class BaseConnection(object):
:param context: The security context
:param audit_template_id: The id of an audit template.
:returns: An audit template.
:raises: AuditTemplateNotFound
:raises: :py:class:`~.AuditTemplateNotFound`
"""
@abc.abstractmethod
@@ -95,7 +191,7 @@ class BaseConnection(object):
:param context: The security context
:param audit_template_uuid: The uuid of an audit template.
:returns: An audit template.
:raises: AuditTemplateNotFound
:raises: :py:class:`~.AuditTemplateNotFound`
"""
def get_audit_template_by_name(self, context, audit_template_name):
@@ -104,7 +200,7 @@ class BaseConnection(object):
:param context: The security context
:param audit_template_name: The name of an audit template.
:returns: An audit template.
:raises: AuditTemplateNotFound
:raises: :py:class:`~.AuditTemplateNotFound`
"""
@abc.abstractmethod
@@ -112,7 +208,7 @@ class BaseConnection(object):
"""Destroy an audit_template.
:param audit_template_id: The id or uuid of an audit template.
:raises: AuditTemplateNotFound
:raises: :py:class:`~.AuditTemplateNotFound`
"""
@abc.abstractmethod
@@ -121,8 +217,8 @@ class BaseConnection(object):
:param audit_template_id: The id or uuid of an audit template.
:returns: An audit template.
:raises: AuditTemplateNotFound
:raises: Invalid
:raises: :py:class:`~.AuditTemplateNotFound`
:raises: :py:class:`~.Invalid`
"""
@abc.abstractmethod
@@ -130,7 +226,7 @@ class BaseConnection(object):
"""Soft delete an audit_template.
:param audit_template_id: The id or uuid of an audit template.
:raises: AuditTemplateNotFound
:raises: :py:class:`~.AuditTemplateNotFound`
"""
@abc.abstractmethod
@@ -171,7 +267,7 @@ class BaseConnection(object):
'deadline': None
}
:returns: An audit.
:raises: AuditAlreadyExists
:raises: :py:class:`~.AuditAlreadyExists`
"""
@abc.abstractmethod
@@ -181,7 +277,7 @@ class BaseConnection(object):
:param context: The security context
:param audit_id: The id of an audit.
:returns: An audit.
:raises: AuditNotFound
:raises: :py:class:`~.AuditNotFound`
"""
@abc.abstractmethod
@@ -191,7 +287,7 @@ class BaseConnection(object):
:param context: The security context
:param audit_uuid: The uuid of an audit.
:returns: An audit.
:raises: AuditNotFound
:raises: :py:class:`~.AuditNotFound`
"""
@abc.abstractmethod
@@ -199,7 +295,7 @@ class BaseConnection(object):
"""Destroy an audit and all associated action plans.
:param audit_id: The id or uuid of an audit.
:raises: AuditNotFound
:raises: :py:class:`~.AuditNotFound`
"""
@abc.abstractmethod
@@ -208,8 +304,8 @@ class BaseConnection(object):
:param audit_id: The id or uuid of an audit.
:returns: An audit.
:raises: AuditNotFound
:raises: Invalid
:raises: :py:class:`~.AuditNotFound`
:raises: :py:class:`~.Invalid`
"""
def soft_delete_audit(self, audit_id):
@@ -217,7 +313,7 @@ class BaseConnection(object):
:param audit_id: The id or uuid of an audit.
:returns: An audit.
:raises: AuditNotFound
:raises: :py:class:`~.AuditNotFound`
"""
@abc.abstractmethod
@@ -259,7 +355,7 @@ class BaseConnection(object):
'aggregate': 'nova aggregate name or uuid'
}
:returns: A action.
:raises: ActionAlreadyExists
:raises: :py:class:`~.ActionAlreadyExists`
"""
@abc.abstractmethod
@@ -269,7 +365,7 @@ class BaseConnection(object):
:param context: The security context
:param action_id: The id of a action.
:returns: A action.
:raises: ActionNotFound
:raises: :py:class:`~.ActionNotFound`
"""
@abc.abstractmethod
@@ -279,7 +375,7 @@ class BaseConnection(object):
:param context: The security context
:param action_uuid: The uuid of a action.
:returns: A action.
:raises: ActionNotFound
:raises: :py:class:`~.ActionNotFound`
"""
@abc.abstractmethod
@@ -287,8 +383,8 @@ class BaseConnection(object):
"""Destroy a action and all associated interfaces.
:param action_id: The id or uuid of a action.
:raises: ActionNotFound
:raises: ActionReferenced
:raises: :py:class:`~.ActionNotFound`
:raises: :py:class:`~.ActionReferenced`
"""
@abc.abstractmethod
@@ -297,9 +393,9 @@ class BaseConnection(object):
:param action_id: The id or uuid of a action.
:returns: A action.
:raises: ActionNotFound
:raises: ActionReferenced
:raises: Invalid
:raises: :py:class:`~.ActionNotFound`
:raises: :py:class:`~.ActionReferenced`
:raises: :py:class:`~.Invalid`
"""
@abc.abstractmethod
@@ -332,7 +428,7 @@ class BaseConnection(object):
:param values: A dict containing several items used to identify
and track the action plan.
:returns: An action plan.
:raises: ActionPlanAlreadyExists
:raises: :py:class:`~.ActionPlanAlreadyExists`
"""
@abc.abstractmethod
@@ -342,7 +438,7 @@ class BaseConnection(object):
:param context: The security context
:param action_plan_id: The id of an action plan.
:returns: An action plan.
:raises: ActionPlanNotFound
:raises: :py:class:`~.ActionPlanNotFound`
"""
@abc.abstractmethod
@@ -352,7 +448,7 @@ class BaseConnection(object):
:param context: The security context
:param action_plan__uuid: The uuid of an action plan.
:returns: An action plan.
:raises: ActionPlanNotFound
:raises: :py:class:`~.ActionPlanNotFound`
"""
@abc.abstractmethod
@@ -360,8 +456,8 @@ class BaseConnection(object):
"""Destroy an action plan and all associated interfaces.
:param action_plan_id: The id or uuid of a action plan.
:raises: ActionPlanNotFound
:raises: ActionPlanReferenced
:raises: :py:class:`~.ActionPlanNotFound`
:raises: :py:class:`~.ActionPlanReferenced`
"""
@abc.abstractmethod
@@ -370,7 +466,7 @@ class BaseConnection(object):
:param action_plan_id: The id or uuid of an action plan.
:returns: An action plan.
:raises: ActionPlanNotFound
:raises: ActionPlanReferenced
:raises: Invalid
:raises: :py:class:`~.ActionPlanNotFound`
:raises: :py:class:`~.ActionPlanReferenced`
:raises: :py:class:`~.Invalid`
"""

View File

@@ -182,6 +182,94 @@ class Connection(api.BaseConnection):
return query
def __add_simple_filter(self, query, model, fieldname, value):
return query.filter(getattr(model, fieldname) == value)
def __add_join_filter(self, query, model, join_model, fieldname, value):
query = query.join(join_model)
return self.__add_simple_filter(query, model, fieldname, value)
def _add_filters(self, query, model, filters=None,
plain_fields=None, join_fieldmap=None):
filters = filters or {}
plain_fields = plain_fields or ()
join_fieldmap = join_fieldmap or {}
for fieldname, value in filters.items():
if fieldname in plain_fields:
query = self.__add_simple_filter(
query, model, fieldname, value)
elif fieldname in join_fieldmap:
join_model = join_fieldmap[fieldname]
query = self.__add_join_filter(
query, model, join_model, fieldname, value)
query = self.__add_soft_delete_mixin_filters(query, filters, model)
query = self.__add_timestamp_mixin_filters(query, filters, model)
return query
def _get(self, context, model, fieldname, value):
query = model_query(model)
query = query.filter(getattr(model, fieldname) == value)
if not context.show_deleted:
query = query.filter(model.deleted_at.is_(None))
try:
obj = query.one()
except exc.NoResultFound:
raise exception.ResourceNotFound(name=model.__name__, id=value)
return obj
def _update(self, model, id_, values):
session = get_session()
with session.begin():
query = model_query(model, session=session)
query = add_identity_filter(query, id_)
try:
ref = query.with_lockmode('update').one()
except exc.NoResultFound:
raise exception.ResourceNotFound(name=model.__name__, id=id_)
ref.update(values)
return ref
def _soft_delete(self, model, id_):
session = get_session()
with session.begin():
query = model_query(model, session=session)
query = add_identity_filter(query, id_)
try:
query.one()
except exc.NoResultFound:
raise exception.ResourceNotFound(name=model.__name__, id=id_)
query.soft_delete()
def _destroy(self, model, id_):
session = get_session()
with session.begin():
query = model_query(model, session=session)
query = add_identity_filter(query, id_)
try:
query.one()
except exc.NoResultFound:
raise exception.ResourceNotFound(name=model.__name__, id=id_)
query.delete()
def _add_goals_filters(self, query, filters):
if filters is None:
filters = {}
plain_fields = ['uuid', 'name', 'display_name']
return self._add_filters(
query=query, model=models.Goal, filters=filters,
plain_fields=plain_fields)
def _add_audit_templates_filters(self, query, filters):
if filters is None:
filters = []
@@ -289,6 +377,72 @@ class Connection(api.BaseConnection):
return query
# ### GOALS ### #
def get_goal_list(self, context, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
query = model_query(models.Goal)
query = self._add_goals_filters(query, filters)
if not context.show_deleted:
query = query.filter_by(deleted_at=None)
return _paginate_query(models.Goal, limit, marker,
sort_key, sort_dir, query)
def create_goal(self, values):
# ensure defaults are present for new goals
if not values.get('uuid'):
values['uuid'] = utils.generate_uuid()
goal = models.Goal()
goal.update(values)
try:
goal.save()
except db_exc.DBDuplicateEntry:
raise exception.GoalAlreadyExists(uuid=values['uuid'])
return goal
def _get_goal(self, context, fieldname, value):
try:
return self._get(context, model=models.Goal,
fieldname=fieldname, value=value)
except exception.ResourceNotFound:
raise exception.GoalNotFound(goal=value)
def get_goal_by_id(self, context, goal_id):
return self._get_goal(context, fieldname="id", value=goal_id)
def get_goal_by_uuid(self, context, goal_uuid):
return self._get_goal(context, fieldname="uuid", value=goal_uuid)
def get_goal_by_name(self, context, goal_name):
return self._get_goal(context, fieldname="name", value=goal_name)
def destroy_goal(self, goal_id):
try:
return self._destroy(models.Goal, goal_id)
except exception.ResourceNotFound:
raise exception.GoalNotFound(goal=goal_id)
def update_goal(self, goal_id, values):
if 'uuid' in values:
raise exception.Invalid(
message=_("Cannot overwrite UUID for an existing Goal."))
try:
return self._update(models.Goal, goal_id, values)
except exception.ResourceNotFound:
raise exception.GoalNotFound(goal=goal_id)
def soft_delete_goal(self, goal_id):
try:
self._soft_delete(models.Goal, goal_id)
except exception.ResourceNotFound:
raise exception.GoalNotFound(goal=goal_id)
# ### AUDIT TEMPLATES ### #
def get_audit_template_list(self, context, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
@@ -373,7 +527,8 @@ class Connection(api.BaseConnection):
try:
query.one()
except exc.NoResultFound:
raise exception.AuditTemplateNotFound(node=audit_template_id)
raise exception.AuditTemplateNotFound(
audit_template=audit_template_id)
query.delete()
@@ -408,10 +563,13 @@ class Connection(api.BaseConnection):
try:
query.one()
except exc.NoResultFound:
raise exception.AuditTemplateNotFound(node=audit_template_id)
raise exception.AuditTemplateNotFound(
audit_template=audit_template_id)
query.soft_delete()
# ### AUDITS ### #
def get_audit_list(self, context, filters=None, limit=None, marker=None,
sort_key=None, sort_dir=None):
query = model_query(models.Audit)
@@ -518,10 +676,12 @@ class Connection(api.BaseConnection):
try:
query.one()
except exc.NoResultFound:
raise exception.AuditNotFound(node=audit_id)
raise exception.AuditNotFound(audit=audit_id)
query.soft_delete()
# ### ACTIONS ### #
def get_action_list(self, context, filters=None, limit=None, marker=None,
sort_key=None, sort_dir=None):
query = model_query(models.Action)
@@ -611,10 +771,12 @@ class Connection(api.BaseConnection):
try:
query.one()
except exc.NoResultFound:
raise exception.ActionNotFound(node=action_id)
raise exception.ActionNotFound(action=action_id)
query.soft_delete()
# ### ACTION PLANS ### #
def get_action_plan_list(
self, context, columns=None, filters=None, limit=None,
marker=None, sort_key=None, sort_dir=None):
@@ -722,6 +884,6 @@ class Connection(api.BaseConnection):
try:
query.one()
except exc.NoResultFound:
raise exception.ActionPlanNotFound(node=action_plan_id)
raise exception.ActionPlanNotFound(action_plan=action_plan_id)
query.soft_delete()

View File

@@ -110,6 +110,20 @@ class WatcherBase(models.SoftDeleteMixin,
Base = declarative_base(cls=WatcherBase)
class Goal(Base):
"""Represents a goal."""
__tablename__ = 'goals'
__table_args__ = (
schema.UniqueConstraint('uuid', name='uniq_goals0uuid'),
table_args(),
)
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
name = Column(String(63), nullable=False)
display_name = Column(String(63), nullable=False)
class AuditTemplate(Base):
"""Represents an audit template."""
@@ -175,9 +189,6 @@ class ActionPlan(Base):
id = Column(Integer, primary_key=True)
uuid = Column(String(36))
first_action_id = Column(Integer)
# first_action_id = Column(Integer, ForeignKeyConstraint(
# ['first_action_id'], ['actions.id'], name='fk_first_action_id'),
# nullable=True)
audit_id = Column(Integer, ForeignKey('audits.id'),
nullable=True)
state = Column(String(20), nullable=True)

View File

@@ -0,0 +1,324 @@
# 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.
"""Tests for manipulating Goal via the DB API"""
import freezegun
import six
from watcher.common import exception
from watcher.common import utils as w_utils
from watcher.tests.db import base
from watcher.tests.db import utils
class TestDbGoalFilters(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(TestDbGoalFilters, self).setUp()
self.context.show_deleted = True
self._data_setup()
def _data_setup(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.goal1 = utils.create_test_goal(
id=1, uuid=w_utils.generate_uuid(), name="GOAL_1",
display_name="Goal 1")
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.goal2 = utils.create_test_goal(
id=2, uuid=w_utils.generate_uuid(),
name="GOAL_2", display_name="Goal 2")
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.goal3 = utils.create_test_goal(
id=3, uuid=w_utils.generate_uuid(),
name="GOAL_3", display_name="Goal 3")
def _soft_delete_goals(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_goal(self.goal1.uuid)
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.dbapi.soft_delete_goal(self.goal2.uuid)
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.dbapi.soft_delete_goal(self.goal3.uuid)
def _update_goals(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.update_goal(
self.goal1.uuid, values={"display_name": "goal1"})
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.dbapi.update_goal(
self.goal2.uuid, values={"display_name": "goal2"})
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.dbapi.update_goal(
self.goal3.uuid, values={"display_name": "goal3"})
def test_get_goal_list_filter_deleted_true(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_goal(self.goal1.uuid)
res = self.dbapi.get_goal_list(
self.context, filters={'deleted': True})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_deleted_false(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_goal(self.goal1.uuid)
res = self.dbapi.get_goal_list(
self.context, filters={'deleted': False})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_deleted_at_eq(self):
self._soft_delete_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'deleted_at__eq': self.FAKE_TODAY})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_deleted_at_lt(self):
self._soft_delete_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'deleted_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_deleted_at_lte(self):
self._soft_delete_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'deleted_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_deleted_at_gt(self):
self._soft_delete_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'deleted_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_deleted_at_gte(self):
self._soft_delete_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'deleted_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal1.uuid, self.goal2.uuid]),
set([r.uuid for r in res]))
# created_at #
def test_get_goal_list_filter_created_at_eq(self):
res = self.dbapi.get_goal_list(
self.context, filters={'created_at__eq': self.FAKE_TODAY})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_created_at_lt(self):
res = self.dbapi.get_goal_list(
self.context, filters={'created_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_created_at_lte(self):
res = self.dbapi.get_goal_list(
self.context, filters={'created_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_created_at_gt(self):
res = self.dbapi.get_goal_list(
self.context, filters={'created_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_created_at_gte(self):
res = self.dbapi.get_goal_list(
self.context, filters={'created_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal1.uuid, self.goal2.uuid]),
set([r.uuid for r in res]))
# updated_at #
def test_get_goal_list_filter_updated_at_eq(self):
self._update_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'updated_at__eq': self.FAKE_TODAY})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_updated_at_lt(self):
self._update_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'updated_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_updated_at_lte(self):
self._update_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'updated_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal2.uuid, self.goal3.uuid]),
set([r.uuid for r in res]))
def test_get_goal_list_filter_updated_at_gt(self):
self._update_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'updated_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.goal1.uuid], [r.uuid for r in res])
def test_get_goal_list_filter_updated_at_gte(self):
self._update_goals()
res = self.dbapi.get_goal_list(
self.context, filters={'updated_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.goal1.uuid, self.goal2.uuid]),
set([r.uuid for r in res]))
class DbGoalTestCase(base.DbTestCase):
def _create_test_goal(self, **kwargs):
goal = utils.get_test_goal(**kwargs)
self.dbapi.create_goal(goal)
return goal
def test_get_goal_list(self):
uuids = []
for i in range(1, 6):
goal = utils.create_test_goal(
id=i,
uuid=w_utils.generate_uuid(),
name="GOAL_%s" % i,
display_name='My Goal %s' % i)
uuids.append(six.text_type(goal['uuid']))
res = self.dbapi.get_goal_list(self.context)
res_uuids = [r.uuid for r in res]
self.assertEqual(uuids.sort(), res_uuids.sort())
def test_get_goal_list_with_filters(self):
goal1_uuid = w_utils.generate_uuid()
goal2_uuid = w_utils.generate_uuid()
goal1 = self._create_test_goal(
id=1,
uuid=goal1_uuid,
name="GOAL_1",
display_name='Goal 1',
)
goal2 = self._create_test_goal(
id=2,
uuid=goal2_uuid,
name="GOAL_2",
display_name='Goal 2',
)
res = self.dbapi.get_goal_list(self.context,
filters={'display_name': 'Goal 1'})
self.assertEqual([goal1['uuid']], [r.uuid for r in res])
res = self.dbapi.get_goal_list(self.context,
filters={'display_name': 'Goal 3'})
self.assertEqual([], [r.uuid for r in res])
res = self.dbapi.get_goal_list(
self.context, filters={'name': 'GOAL_1'})
self.assertEqual([goal1['uuid']], [r.uuid for r in res])
res = self.dbapi.get_goal_list(
self.context,
filters={'display_name': 'Goal 2'})
self.assertEqual([goal2['uuid']], [r.uuid for r in res])
def test_get_goal_by_uuid(self):
created_goal = self._create_test_goal()
goal = self.dbapi.get_goal_by_uuid(self.context, created_goal['uuid'])
self.assertEqual(goal.uuid, created_goal['uuid'])
def test_get_goal_that_does_not_exist(self):
random_uuid = w_utils.generate_uuid()
self.assertRaises(exception.GoalNotFound,
self.dbapi.get_goal_by_uuid,
self.context, random_uuid)
def test_update_goal(self):
goal = self._create_test_goal()
res = self.dbapi.update_goal(goal['uuid'],
{'display_name': 'updated-model'})
self.assertEqual('updated-model', res.display_name)
def test_update_goal_id(self):
goal = self._create_test_goal()
self.assertRaises(exception.Invalid,
self.dbapi.update_goal, goal['uuid'],
{'uuid': 'NEW_GOAL'})
def test_update_goal_that_does_not_exist(self):
random_uuid = w_utils.generate_uuid()
self.assertRaises(exception.GoalNotFound,
self.dbapi.update_goal,
random_uuid,
{'display_name': ''})
def test_destroy_goal(self):
goal = self._create_test_goal()
self.dbapi.destroy_goal(goal['uuid'])
self.assertRaises(exception.GoalNotFound,
self.dbapi.get_goal_by_uuid,
self.context, goal['uuid'])
def test_destroy_goal_that_does_not_exist(self):
random_uuid = w_utils.generate_uuid()
self.assertRaises(exception.GoalNotFound,
self.dbapi.destroy_goal, random_uuid)
def test_create_goal_already_exists(self):
goal_uuid = w_utils.generate_uuid()
self._create_test_goal(uuid=goal_uuid)
self.assertRaises(exception.GoalAlreadyExists,
self._create_test_goal,
uuid=goal_uuid)

View File

@@ -127,7 +127,7 @@ def get_test_action_plan(**kwargs):
def create_test_action_plan(**kwargs):
"""Create test action plan entry in DB and return Action DB object.
"""Create test action plan entry in DB and return Action Plan DB object.
Function to be used to create test Action objects in the database.
:param kwargs: kwargsargs with overriding values for action's attributes.
@@ -139,3 +139,27 @@ def create_test_action_plan(**kwargs):
del action['id']
dbapi = db_api.get_instance()
return dbapi.create_action_plan(action)
def get_test_goal(**kwargs):
return {
'id': kwargs.get('id', 1),
'uuid': kwargs.get('uuid', 'f7ad87ae-4298-91cf-93a0-f35a852e3652'),
'name': kwargs.get('name', 'TEST'),
'display_name': kwargs.get('display_name', 'test goal'),
'created_at': kwargs.get('created_at'),
'updated_at': kwargs.get('updated_at'),
'deleted_at': kwargs.get('deleted_at'),
}
def create_test_goal(**kwargs):
"""Create test goal entry in DB and return Goal DB object.
Function to be used to create test Goal objects in the database.
:param kwargs: kwargs which override default goal values of its attributes.
:returns: Test Goal DB object.
"""
goal = get_test_goal(**kwargs)
dbapi = db_api.get_instance()
return dbapi.create_goal(goal)