dynamic action description

Add a new table to save the mapping
Add logic to update the table when action loading
Add logic to show the action description

Change-Id: Ia008a8715bcc666ab0fefe444ef612394c775e91
Implements: blueprint dynamic-action-description
This commit is contained in:
licanwei
2017-07-15 02:25:43 -07:00
parent 0ddfa278ef
commit a24b7f0b61
15 changed files with 771 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ import types
import mock
from oslo_config import cfg
from oslo_service import service
from watcher.applier import sync
from watcher.common import service as watcher_service
from watcher.cmd import applier
@@ -49,6 +50,7 @@ class TestApplier(base.BaseTestCase):
super(TestApplier, self).tearDown()
self.conf._parse_cli_opts = self._parse_cli_opts
@mock.patch.object(sync.Syncer, "sync", mock.Mock())
@mock.patch.object(service, "launch")
def test_run_applier_app(self, m_launch):
applier.main()

View File

@@ -0,0 +1,293 @@
# -*- encoding: utf-8 -*-
# Copyright (c) 2017 ZTE
#
# 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 ActionDescription via the DB API"""
import freezegun
from watcher.common import exception
from watcher.tests.db import base
from watcher.tests.db import utils
class TestDbActionDescriptionFilters(base.DbTestCase):
FAKE_OLDER_DATE = '2015-01-01T09:52:05.219414'
FAKE_OLD_DATE = '2016-01-01T09:52:05.219414'
FAKE_TODAY = '2017-02-24T09:52:05.219414'
def setUp(self):
super(TestDbActionDescriptionFilters, self).setUp()
self.context.show_deleted = True
self._data_setup()
def _data_setup(self):
action_desc1_type = "nop"
action_desc2_type = "sleep"
action_desc3_type = "resize"
with freezegun.freeze_time(self.FAKE_TODAY):
self.action_desc1 = utils.create_test_action_desc(
id=1, action_type=action_desc1_type,
description="description")
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.action_desc2 = utils.create_test_action_desc(
id=2, action_type=action_desc2_type,
description="description")
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.action_desc3 = utils.create_test_action_desc(
id=3, action_type=action_desc3_type,
description="description")
def _soft_delete_action_descs(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_action_description(self.action_desc1.id)
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.dbapi.soft_delete_action_description(self.action_desc2.id)
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.dbapi.soft_delete_action_description(self.action_desc3.id)
def _update_action_descs(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.update_action_description(
self.action_desc1.id, values={"description":
"nop description"})
with freezegun.freeze_time(self.FAKE_OLD_DATE):
self.dbapi.update_action_description(
self.action_desc2.id, values={"description":
"sleep description"})
with freezegun.freeze_time(self.FAKE_OLDER_DATE):
self.dbapi.update_action_description(
self.action_desc3.id, values={"description":
"resize description"})
def test_get_action_desc_list_filter_deleted_true(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_action_description(self.action_desc1.id)
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted': True})
self.assertEqual([self.action_desc1['action_type']],
[r.action_type for r in res])
def test_get_action_desc_list_filter_deleted_false(self):
with freezegun.freeze_time(self.FAKE_TODAY):
self.dbapi.soft_delete_action_description(self.action_desc1.id)
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted': False})
self.assertEqual(
set([self.action_desc2['action_type'],
self.action_desc3['action_type']]),
set([r.action_type for r in res]))
def test_get_action_desc_list_filter_deleted_at_eq(self):
self._soft_delete_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted_at__eq': self.FAKE_TODAY})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_deleted_at_lt(self):
self._soft_delete_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_deleted_at_lte(self):
self._soft_delete_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_deleted_at_gt(self):
self._soft_delete_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_deleted_at_gte(self):
self._soft_delete_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'deleted_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc1['id'], self.action_desc2['id']]),
set([r.id for r in res]))
# created_at #
def test_get_action_desc_list_filter_created_at_eq(self):
res = self.dbapi.get_action_description_list(
self.context, filters={'created_at__eq': self.FAKE_TODAY})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_created_at_lt(self):
res = self.dbapi.get_action_description_list(
self.context, filters={'created_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_created_at_lte(self):
res = self.dbapi.get_action_description_list(
self.context, filters={'created_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_created_at_gt(self):
res = self.dbapi.get_action_description_list(
self.context, filters={'created_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_created_at_gte(self):
res = self.dbapi.get_action_description_list(
self.context, filters={'created_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc1['id'], self.action_desc2['id']]),
set([r.id for r in res]))
# updated_at #
def test_get_action_desc_list_filter_updated_at_eq(self):
self._update_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'updated_at__eq': self.FAKE_TODAY})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_updated_at_lt(self):
self._update_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'updated_at__lt': self.FAKE_TODAY})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_updated_at_lte(self):
self._update_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'updated_at__lte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc2['id'], self.action_desc3['id']]),
set([r.id for r in res]))
def test_get_action_desc_list_filter_updated_at_gt(self):
self._update_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'updated_at__gt': self.FAKE_OLD_DATE})
self.assertEqual([self.action_desc1['id']], [r.id for r in res])
def test_get_action_desc_list_filter_updated_at_gte(self):
self._update_action_descs()
res = self.dbapi.get_action_description_list(
self.context, filters={'updated_at__gte': self.FAKE_OLD_DATE})
self.assertEqual(
set([self.action_desc1['id'], self.action_desc2['id']]),
set([r.id for r in res]))
class DbActionDescriptionTestCase(base.DbTestCase):
def _create_test_action_desc(self, **kwargs):
action_desc = utils.get_test_action_desc(**kwargs)
self.dbapi.create_action_description(action_desc)
return action_desc
def test_get_action_desc_list(self):
ids = []
for i in range(1, 4):
action_desc = utils.create_test_action_desc(
id=i,
action_type="action_%s" % i,
description="description_{0}".format(i))
ids.append(action_desc['id'])
action_descs = self.dbapi.get_action_description_list(self.context)
action_desc_ids = [s.id for s in action_descs]
self.assertEqual(sorted(ids), sorted(action_desc_ids))
def test_get_action_desc_list_with_filters(self):
action_desc1 = self._create_test_action_desc(
id=1,
action_type="action_1",
description="description_1",
)
action_desc2 = self._create_test_action_desc(
id=2,
action_type="action_2",
description="description_2",
)
res = self.dbapi.get_action_description_list(
self.context, filters={'action_type': 'action_1'})
self.assertEqual([action_desc1['id']], [r.id for r in res])
res = self.dbapi.get_action_description_list(
self.context, filters={'action_type': 'action_3'})
self.assertEqual([], [r.id for r in res])
res = self.dbapi.get_action_description_list(
self.context,
filters={'action_type': 'action_2'})
self.assertEqual([action_desc2['id']], [r.id for r in res])
def test_get_action_desc_by_type(self):
created_action_desc = self._create_test_action_desc()
action_desc = self.dbapi.get_action_description_by_type(
self.context, created_action_desc['action_type'])
self.assertEqual(action_desc.action_type,
created_action_desc['action_type'])
def test_get_action_desc_that_does_not_exist(self):
self.assertRaises(exception.ActionDescriptionNotFound,
self.dbapi.get_action_description_by_id,
self.context, 404)
def test_update_action_desc(self):
action_desc = self._create_test_action_desc()
res = self.dbapi.update_action_description(
action_desc['id'], {'description': 'description_test'})
self.assertEqual('description_test', res.description)

View File

@@ -331,3 +331,26 @@ def create_test_efficacy_indicator(**kwargs):
del efficacy_indicator['id']
dbapi = db_api.get_instance()
return dbapi.create_efficacy_indicator(efficacy_indicator)
def get_test_action_desc(**kwargs):
return {
'id': kwargs.get('id', 1),
'action_type': kwargs.get('action_type', 'nop'),
'description': kwargs.get('description', 'Logging a NOP message'),
'created_at': kwargs.get('created_at'),
'updated_at': kwargs.get('updated_at'),
'deleted_at': kwargs.get('deleted_at'),
}
def create_test_action_desc(**kwargs):
"""Create test action description entry in DB and return ActionDescription.
Function to be used to create test ActionDescription objects in the DB.
:param kwargs: kwargs with overriding values for service's attributes.
:returns: Test ActionDescription DB object.
"""
action_desc = get_test_action_desc(**kwargs)
dbapi = db_api.get_instance()
return dbapi.create_action_description(action_desc)

View File

@@ -0,0 +1,120 @@
# -*- encoding: utf-8 -*-
# Copyright 2017 ZTE
# 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 datetime
import iso8601
import mock
from watcher.db.sqlalchemy import api as db_api
from watcher import objects
from watcher.tests.db import base
from watcher.tests.db import utils
class TestActionDescriptionObject(base.DbTestCase):
def setUp(self):
super(TestActionDescriptionObject, self).setUp()
self.fake_action_desc = utils.get_test_action_desc(
created_at=datetime.datetime.utcnow())
@mock.patch.object(db_api.Connection, 'get_action_description_by_id')
def test_get_by_id(self, mock_get_action_desc):
action_desc_id = self.fake_action_desc['id']
mock_get_action_desc.return_value = self.fake_action_desc
action_desc = objects.ActionDescription.get(
self.context, action_desc_id)
mock_get_action_desc.assert_called_once_with(
self.context, action_desc_id)
self.assertEqual(self.context, action_desc._context)
@mock.patch.object(db_api.Connection, 'get_action_description_list')
def test_list(self, mock_get_list):
mock_get_list.return_value = [self.fake_action_desc]
action_desc = objects.ActionDescription.list(self.context)
self.assertEqual(1, mock_get_list.call_count)
self.assertEqual(1, len(action_desc))
self.assertIsInstance(action_desc[0], objects.ActionDescription)
self.assertEqual(self.context, action_desc[0]._context)
@mock.patch.object(db_api.Connection, 'create_action_description')
def test_create(self, mock_create_action_desc):
mock_create_action_desc.return_value = self.fake_action_desc
action_desc = objects.ActionDescription(
self.context, **self.fake_action_desc)
action_desc.create()
expected_action_desc = self.fake_action_desc.copy()
expected_action_desc['created_at'] = expected_action_desc[
'created_at'].replace(tzinfo=iso8601.iso8601.Utc())
mock_create_action_desc.assert_called_once_with(expected_action_desc)
self.assertEqual(self.context, action_desc._context)
@mock.patch.object(db_api.Connection, 'update_action_description')
@mock.patch.object(db_api.Connection, 'get_action_description_by_id')
def test_save(self, mock_get_action_desc, mock_update_action_desc):
mock_get_action_desc.return_value = self.fake_action_desc
fake_saved_action_desc = self.fake_action_desc.copy()
fake_saved_action_desc['updated_at'] = datetime.datetime.utcnow()
mock_update_action_desc.return_value = fake_saved_action_desc
_id = self.fake_action_desc['id']
action_desc = objects.ActionDescription.get(self.context, _id)
action_desc.description = 'This is a test'
action_desc.save()
mock_get_action_desc.assert_called_once_with(self.context, _id)
mock_update_action_desc.assert_called_once_with(
_id, {'description': 'This is a test'})
self.assertEqual(self.context, action_desc._context)
@mock.patch.object(db_api.Connection, 'get_action_description_by_id')
def test_refresh(self, mock_get_action_desc):
returns = [dict(self.fake_action_desc, description="Test message1"),
dict(self.fake_action_desc, description="Test message2")]
mock_get_action_desc.side_effect = returns
_id = self.fake_action_desc['id']
expected = [mock.call(self.context, _id),
mock.call(self.context, _id)]
action_desc = objects.ActionDescription.get(self.context, _id)
self.assertEqual("Test message1", action_desc.description)
action_desc.refresh()
self.assertEqual("Test message2", action_desc.description)
self.assertEqual(expected, mock_get_action_desc.call_args_list)
self.assertEqual(self.context, action_desc._context)
@mock.patch.object(db_api.Connection, 'soft_delete_action_description')
@mock.patch.object(db_api.Connection, 'get_action_description_by_id')
def test_soft_delete(self, mock_get_action_desc, mock_soft_delete):
mock_get_action_desc.return_value = self.fake_action_desc
fake_deleted_action_desc = self.fake_action_desc.copy()
fake_deleted_action_desc['deleted_at'] = datetime.datetime.utcnow()
mock_soft_delete.return_value = fake_deleted_action_desc
expected_action_desc = fake_deleted_action_desc.copy()
expected_action_desc['created_at'] = expected_action_desc[
'created_at'].replace(tzinfo=iso8601.iso8601.Utc())
expected_action_desc['deleted_at'] = expected_action_desc[
'deleted_at'].replace(tzinfo=iso8601.iso8601.Utc())
_id = self.fake_action_desc['id']
action_desc = objects.ActionDescription.get(self.context, _id)
action_desc.soft_delete()
mock_get_action_desc.assert_called_once_with(self.context, _id)
mock_soft_delete.assert_called_once_with(_id)
self.assertEqual(self.context, action_desc._context)
self.assertEqual(expected_action_desc, action_desc.as_dict())

View File

@@ -419,6 +419,7 @@ expected_object_fingerprints = {
'ScoringEngine': '1.0-4abbe833544000728e17bd9e83f97576',
'Service': '1.0-4b35b99ada9677a882c9de2b30212f35',
'MyObj': '1.5-23c516d1e842f365f694e688d34e47c3',
'ActionDescription': '1.0-5761a3d16651046e7a0c357b57a6583e'
}