Added efficacy specification to /goals

In this changeset, I added the new Efficacy, EfficacySpecification
and IndicatorSpecification classes which are the main components for
computing an efficacy.

Partially Implements: blueprint efficacy-indicator

Change-Id: I3a1d62569de2dd6bb6f9a52f6058313fa2b886ce
This commit is contained in:
Vincent Françoise
2016-05-18 15:55:04 +02:00
parent eab47bf182
commit f665d83657
16 changed files with 450 additions and 22 deletions

View File

@@ -21,7 +21,8 @@ from watcher.tests.objects import utils as obj_utils
class TestListGoal(api_base.FunctionalTest):
def _assert_goal_fields(self, goal):
goal_fields = ['uuid', 'name', 'display_name']
goal_fields = ['uuid', 'name', 'display_name',
'efficacy_specification']
for field in goal_fields:
self.assertIn(field, goal)

View File

@@ -151,6 +151,7 @@ def get_test_goal(**kwargs):
'created_at': kwargs.get('created_at'),
'updated_at': kwargs.get('updated_at'),
'deleted_at': kwargs.get('deleted_at'),
'efficacy_specification': kwargs.get('efficacy_specification', []),
}

View File

@@ -14,7 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import voluptuous
from watcher.decision_engine.goal import base as base_goal
from watcher.decision_engine.goal.efficacy import base as efficacy_base
from watcher.decision_engine.goal.efficacy import indicators
from watcher.decision_engine.goal.efficacy import specs
class FakeGoal(base_goal.Goal):
@@ -34,11 +39,44 @@ class FakeGoal(base_goal.Goal):
def get_translatable_display_name(cls):
return cls.DISPLAY_NAME
@classmethod
def get_efficacy_specification(cls):
"""The efficacy spec for the current goal"""
return specs.Unclassified()
class DummyIndicator(indicators.IndicatorSpecification):
def __init__(self):
super(DummyIndicator, self).__init__(
name="dummy",
description="Dummy indicator",
unit="%",
)
@property
def schema(self):
return voluptuous.Schema(
voluptuous.Range(min=0, max=100), required=True)
class DummySpec1(efficacy_base.EfficacySpecification):
def get_indicators_specifications(self):
return [DummyIndicator()]
def get_global_efficacy_indicator(self, indicators_map):
return None
class FakeDummy1(FakeGoal):
NAME = "dummy_1"
DISPLAY_NAME = "Dummy 1"
@classmethod
def get_efficacy_specification(cls):
"""The efficacy spec for the current goal"""
return DummySpec1()
class FakeDummy2(FakeGoal):
NAME = "dummy_2"

View File

@@ -49,6 +49,11 @@ class TestSyncer(base.DbTestCase):
fake_goals.FakeDummy2.get_name(): fake_goals.FakeDummy2,
})
self.goal1_spec = fake_goals.FakeDummy1(
config=mock.Mock()).get_efficacy_specification()
self.goal2_spec = fake_goals.FakeDummy2(
config=mock.Mock()).get_efficacy_specification()
p_goals_load = mock.patch.object(
default.DefaultGoalLoader, 'load',
side_effect=lambda goal: self.m_available_goals()[goal]())
@@ -111,7 +116,9 @@ class TestSyncer(base.DbTestCase):
objects.Goal(self.ctx, id=i) for i in range(1, 10)]
m_g_list.return_value = [
objects.Goal(self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_1", display_name="Dummy 1",)
name="dummy_1", display_name="Dummy 1",
efficacy_specification=(
self.goal1_spec.serialize_indicators_specs()))
]
m_s_list.return_value = []
@@ -141,7 +148,9 @@ class TestSyncer(base.DbTestCase):
objects.Goal(self.ctx, id=i) for i in range(1, 10)]
m_g_list.return_value = [
objects.Goal(self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_1", display_name="Dummy 1",)
name="dummy_1", display_name="Dummy 1",
efficacy_specification=(
self.goal1_spec.serialize_indicators_specs()))
]
m_s_list.return_value = [
objects.Strategy(self.ctx, id=1, name="strategy_1",
@@ -174,6 +183,7 @@ class TestSyncer(base.DbTestCase):
m_g_list.return_value = [objects.Goal(
self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_2", display_name="original",
efficacy_specification=self.goal2_spec.serialize_indicators_specs()
)]
m_s_list.return_value = []
self.syncer.sync()
@@ -202,7 +212,9 @@ class TestSyncer(base.DbTestCase):
objects.Goal(self.ctx, id=i) for i in range(1, 10)]
m_g_list.return_value = [
objects.Goal(self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_1", display_name="Dummy 1",)
name="dummy_1", display_name="Dummy 1",
efficacy_specification=(
self.goal1_spec.serialize_indicators_specs()))
]
m_s_list.return_value = [
objects.Strategy(self.ctx, id=1, name="strategy_1",
@@ -227,11 +239,14 @@ class TestSyncer(base.DbTestCase):
# Should stay unmodified after sync()
goal1 = objects.Goal(
self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_1", display_name="Dummy 1",)
name="dummy_1", display_name="Dummy 1",
efficacy_specification=(
self.goal1_spec.serialize_indicators_specs()))
# Should be modified by the sync()
goal2 = objects.Goal(
self.ctx, id=2, uuid=utils.generate_uuid(),
name="dummy_2", display_name="Original",
efficacy_specification=self.goal2_spec.serialize_indicators_specs()
)
goal1.create()
goal2.create()
@@ -322,6 +337,16 @@ class TestSyncer(base.DbTestCase):
if a_s.uuid not in [b_s.uuid for b_s in before_strategies]
}
dummy_1_spec = [
{'description': 'Dummy indicator', 'name': 'dummy',
'schema': 'Range(min=0, max=100, min_included=True, '
'max_included=True, msg=None)',
'unit': '%'}]
dummy_2_spec = []
self.assertEqual(
[dummy_1_spec, dummy_2_spec],
[g.efficacy_specification for g in after_goals])
self.assertEqual(1, len(created_goals))
self.assertEqual(3, len(created_strategies))
@@ -374,11 +399,13 @@ class TestSyncer(base.DbTestCase):
goal1 = objects.Goal(
self.ctx, id=1, uuid=utils.generate_uuid(),
name="dummy_1", display_name="Dummy 1",
efficacy_specification=self.goal1_spec.serialize_indicators_specs()
)
# To be removed by the sync()
goal2 = objects.Goal(
self.ctx, id=2, uuid=utils.generate_uuid(),
name="dummy_2", display_name="Dummy 2",
efficacy_specification=self.goal2_spec.serialize_indicators_specs()
)
goal1.create()
goal2.create()