Introduce the execute-mistral action. This patch includes validating the action, and converting it to a general-purpose ExecuteExternal step.
The following will be done in the *next* patches: * Implementation of the ExternalExecute step * Implementation of the Mistral notifier * Documentation of the new action Change-Id: I571861149e51bca85cb024969b8595ae85655b25 Implements: blueprint integration-with-mistral
This commit is contained in:
parent
d7397d7943
commit
5057c96f5e
@ -101,3 +101,6 @@ The following describes all the possible status code and their messages:
|
|||||||
| 132 | add_causal_relationship action requires action_target to| content |
|
| 132 | add_causal_relationship action requires action_target to| content |
|
||||||
| | be ALARM | |
|
| | be ALARM | |
|
||||||
+------------------+---------------------------------------------------------+-------------------------------+
|
+------------------+---------------------------------------------------------+-------------------------------+
|
||||||
|
| 133 | execute_mistral action must contain workflow field in | content |
|
||||||
|
| | properties block | |
|
||||||
|
+------------------+---------------------------------------------------------+-------------------------------+
|
||||||
|
@ -25,12 +25,14 @@ from vitrage.evaluator.actions.evaluator_event_transformer \
|
|||||||
import VITRAGE_DATASOURCE
|
import VITRAGE_DATASOURCE
|
||||||
from vitrage.evaluator.actions.recipes.action_steps import ADD_EDGE
|
from vitrage.evaluator.actions.recipes.action_steps import ADD_EDGE
|
||||||
from vitrage.evaluator.actions.recipes.action_steps import ADD_VERTEX
|
from vitrage.evaluator.actions.recipes.action_steps import ADD_VERTEX
|
||||||
|
from vitrage.evaluator.actions.recipes.action_steps import EXECUTE_EXTERNAL
|
||||||
from vitrage.evaluator.actions.recipes.action_steps import REMOVE_EDGE
|
from vitrage.evaluator.actions.recipes.action_steps import REMOVE_EDGE
|
||||||
from vitrage.evaluator.actions.recipes.action_steps import REMOVE_VERTEX
|
from vitrage.evaluator.actions.recipes.action_steps import REMOVE_VERTEX
|
||||||
from vitrage.evaluator.actions.recipes.action_steps import UPDATE_VERTEX
|
from vitrage.evaluator.actions.recipes.action_steps import UPDATE_VERTEX
|
||||||
from vitrage.evaluator.actions.recipes.add_causal_relationship import \
|
from vitrage.evaluator.actions.recipes.add_causal_relationship import \
|
||||||
AddCausalRelationship
|
AddCausalRelationship
|
||||||
from vitrage.evaluator.actions.recipes.base import EVALUATOR_EVENT_TYPE
|
from vitrage.evaluator.actions.recipes.base import EVALUATOR_EVENT_TYPE
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import ExecuteMistral
|
||||||
from vitrage.evaluator.actions.recipes.mark_down import MarkDown
|
from vitrage.evaluator.actions.recipes.mark_down import MarkDown
|
||||||
from vitrage.evaluator.actions.recipes.raise_alarm import RaiseAlarm
|
from vitrage.evaluator.actions.recipes.raise_alarm import RaiseAlarm
|
||||||
from vitrage.evaluator.actions.recipes.set_state import SetState
|
from vitrage.evaluator.actions.recipes.set_state import SetState
|
||||||
@ -44,11 +46,12 @@ class ActionExecutor(object):
|
|||||||
self.action_recipes = ActionExecutor._register_action_recipes()
|
self.action_recipes = ActionExecutor._register_action_recipes()
|
||||||
|
|
||||||
self.action_step_defs = {
|
self.action_step_defs = {
|
||||||
ADD_VERTEX: self.add_vertex,
|
ADD_VERTEX: self._add_vertex,
|
||||||
REMOVE_VERTEX: self.remove_vertex,
|
REMOVE_VERTEX: self._remove_vertex,
|
||||||
UPDATE_VERTEX: self.update_vertex,
|
UPDATE_VERTEX: self._update_vertex,
|
||||||
ADD_EDGE: self.add_edge,
|
ADD_EDGE: self._add_edge,
|
||||||
REMOVE_EDGE: self.remove_edge,
|
REMOVE_EDGE: self._remove_edge,
|
||||||
|
EXECUTE_EXTERNAL: self._execute_external,
|
||||||
}
|
}
|
||||||
|
|
||||||
def execute(self, action_spec, action_mode):
|
def execute(self, action_spec, action_mode):
|
||||||
@ -62,7 +65,7 @@ class ActionExecutor(object):
|
|||||||
for step in steps:
|
for step in steps:
|
||||||
self.action_step_defs[step.type](step.params)
|
self.action_step_defs[step.type](step.params)
|
||||||
|
|
||||||
def add_vertex(self, params):
|
def _add_vertex(self, params):
|
||||||
|
|
||||||
event = copy.deepcopy(params)
|
event = copy.deepcopy(params)
|
||||||
ActionExecutor._add_default_properties(event)
|
ActionExecutor._add_default_properties(event)
|
||||||
@ -70,7 +73,7 @@ class ActionExecutor(object):
|
|||||||
|
|
||||||
self.event_queue.put(event)
|
self.event_queue.put(event)
|
||||||
|
|
||||||
def update_vertex(self, params):
|
def _update_vertex(self, params):
|
||||||
|
|
||||||
event = copy.deepcopy(params)
|
event = copy.deepcopy(params)
|
||||||
ActionExecutor._add_default_properties(event)
|
ActionExecutor._add_default_properties(event)
|
||||||
@ -78,14 +81,14 @@ class ActionExecutor(object):
|
|||||||
|
|
||||||
self.event_queue.put(event)
|
self.event_queue.put(event)
|
||||||
|
|
||||||
def remove_vertex(self, params):
|
def _remove_vertex(self, params):
|
||||||
event = copy.deepcopy(params)
|
event = copy.deepcopy(params)
|
||||||
ActionExecutor._add_default_properties(event)
|
ActionExecutor._add_default_properties(event)
|
||||||
event[EVALUATOR_EVENT_TYPE] = REMOVE_VERTEX
|
event[EVALUATOR_EVENT_TYPE] = REMOVE_VERTEX
|
||||||
|
|
||||||
self.event_queue.put(event)
|
self.event_queue.put(event)
|
||||||
|
|
||||||
def add_edge(self, params):
|
def _add_edge(self, params):
|
||||||
|
|
||||||
event = copy.deepcopy(params)
|
event = copy.deepcopy(params)
|
||||||
ActionExecutor._add_default_properties(event)
|
ActionExecutor._add_default_properties(event)
|
||||||
@ -93,7 +96,7 @@ class ActionExecutor(object):
|
|||||||
|
|
||||||
self.event_queue.put(event)
|
self.event_queue.put(event)
|
||||||
|
|
||||||
def remove_edge(self, params):
|
def _remove_edge(self, params):
|
||||||
|
|
||||||
event = copy.deepcopy(params)
|
event = copy.deepcopy(params)
|
||||||
ActionExecutor._add_default_properties(event)
|
ActionExecutor._add_default_properties(event)
|
||||||
@ -101,6 +104,12 @@ class ActionExecutor(object):
|
|||||||
|
|
||||||
self.event_queue.put(event)
|
self.event_queue.put(event)
|
||||||
|
|
||||||
|
def _execute_external(self, params):
|
||||||
|
|
||||||
|
# TODO(ifat_afek): send to a dedicated queue
|
||||||
|
# external_engine = params[EXECUTION_ENGINE]
|
||||||
|
pass
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _add_default_properties(event):
|
def _add_default_properties(event):
|
||||||
|
|
||||||
@ -129,4 +138,7 @@ class ActionExecutor(object):
|
|||||||
recipes[ActionType.MARK_DOWN] = importutils.import_object(
|
recipes[ActionType.MARK_DOWN] = importutils.import_object(
|
||||||
"%s.%s" % (MarkDown.__module__, MarkDown.__name__))
|
"%s.%s" % (MarkDown.__module__, MarkDown.__name__))
|
||||||
|
|
||||||
|
recipes[ActionType.EXECUTE_MISTRAL] = importutils.import_object(
|
||||||
|
"%s.%s" % (ExecuteMistral.__module__, ExecuteMistral.__name__))
|
||||||
|
|
||||||
return recipes
|
return recipes
|
||||||
|
@ -19,11 +19,13 @@ class ActionType(object):
|
|||||||
RAISE_ALARM = 'raise_alarm'
|
RAISE_ALARM = 'raise_alarm'
|
||||||
ADD_CAUSAL_RELATIONSHIP = 'add_causal_relationship'
|
ADD_CAUSAL_RELATIONSHIP = 'add_causal_relationship'
|
||||||
MARK_DOWN = 'mark_down'
|
MARK_DOWN = 'mark_down'
|
||||||
|
EXECUTE_MISTRAL = 'execute_mistral'
|
||||||
|
|
||||||
action_types = [ActionType.SET_STATE,
|
action_types = [ActionType.SET_STATE,
|
||||||
ActionType.RAISE_ALARM,
|
ActionType.RAISE_ALARM,
|
||||||
ActionType.ADD_CAUSAL_RELATIONSHIP,
|
ActionType.ADD_CAUSAL_RELATIONSHIP,
|
||||||
ActionType.MARK_DOWN]
|
ActionType.MARK_DOWN,
|
||||||
|
ActionType.EXECUTE_MISTRAL]
|
||||||
|
|
||||||
|
|
||||||
class ActionMode(object):
|
class ActionMode(object):
|
||||||
|
@ -17,3 +17,6 @@ REMOVE_VERTEX = 'remove_vertex'
|
|||||||
UPDATE_VERTEX = 'update_vertex'
|
UPDATE_VERTEX = 'update_vertex'
|
||||||
ADD_EDGE = 'add_edge'
|
ADD_EDGE = 'add_edge'
|
||||||
REMOVE_EDGE = 'remove_edge'
|
REMOVE_EDGE = 'remove_edge'
|
||||||
|
EXECUTE_EXTERNAL = 'execute_external'
|
||||||
|
|
||||||
|
EXECUTION_ENGINE = 'execution_engine'
|
||||||
|
59
vitrage/evaluator/actions/recipes/execute_mistral.py
Normal file
59
vitrage/evaluator/actions/recipes/execute_mistral.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Copyright 2017 - Nokia
|
||||||
|
#
|
||||||
|
# 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 vitrage.evaluator.actions.recipes.action_steps import EXECUTE_EXTERNAL
|
||||||
|
from vitrage.evaluator.actions.recipes.action_steps import EXECUTION_ENGINE
|
||||||
|
from vitrage.evaluator.actions.recipes import base
|
||||||
|
from vitrage.evaluator.actions.recipes.base import ActionStepWrapper
|
||||||
|
|
||||||
|
|
||||||
|
MISTRAL = 'mistral'
|
||||||
|
WORKFLOW = 'workflow'
|
||||||
|
|
||||||
|
|
||||||
|
class ExecuteMistral(base.Recipe):
|
||||||
|
"""Execute a Mistral workflow
|
||||||
|
|
||||||
|
The 'get_do_recipe' and 'get_undo_recipe' receive action_spec as input.
|
||||||
|
The action_spec contains the following fields: type and properties.
|
||||||
|
|
||||||
|
example input:
|
||||||
|
|
||||||
|
action_spec = ActionSpecs('type'= {'execute_mistral'},
|
||||||
|
'properties' = {workflow : wf_1,
|
||||||
|
host: host_2,
|
||||||
|
host_status: down}
|
||||||
|
"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_do_recipe(action_spec):
|
||||||
|
|
||||||
|
execute_external_step = ExecuteMistral._get_execute_external_step(
|
||||||
|
action_spec.properties
|
||||||
|
)
|
||||||
|
|
||||||
|
return [execute_external_step]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_undo_recipe(action_spec):
|
||||||
|
# No undo for execute an external action
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_execute_external_step(properties):
|
||||||
|
|
||||||
|
properties[EXECUTION_ENGINE] = MISTRAL
|
||||||
|
execute_external_step = ActionStepWrapper(EXECUTE_EXTERNAL,
|
||||||
|
properties)
|
||||||
|
|
||||||
|
return execute_external_step
|
@ -382,7 +382,8 @@ class ActionTracker(object):
|
|||||||
ActionType.SET_STATE: pt.SetStateTools(all_scores),
|
ActionType.SET_STATE: pt.SetStateTools(all_scores),
|
||||||
ActionType.RAISE_ALARM: pt.RaiseAlarmTools(alarms_score),
|
ActionType.RAISE_ALARM: pt.RaiseAlarmTools(alarms_score),
|
||||||
ActionType.ADD_CAUSAL_RELATIONSHIP: pt.BaselineTools,
|
ActionType.ADD_CAUSAL_RELATIONSHIP: pt.BaselineTools,
|
||||||
ActionType.MARK_DOWN: pt.BaselineTools
|
ActionType.MARK_DOWN: pt.BaselineTools,
|
||||||
|
ActionType.EXECUTE_MISTRAL: pt.BaselineTools
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_key(self, action_specs):
|
def get_key(self, action_specs):
|
||||||
|
@ -274,7 +274,7 @@ class TemplateData(object):
|
|||||||
|
|
||||||
action_dict = action_def[TFields.ACTION]
|
action_dict = action_def[TFields.ACTION]
|
||||||
action_type = action_dict[TFields.ACTION_TYPE]
|
action_type = action_dict[TFields.ACTION_TYPE]
|
||||||
targets = action_dict[TFields.ACTION_TARGET]
|
targets = action_dict.get(TFields.ACTION_TARGET, {})
|
||||||
properties = action_dict.get(TFields.PROPERTIES, {})
|
properties = action_dict.get(TFields.PROPERTIES, {})
|
||||||
|
|
||||||
actions.append(ActionSpecs(action_type, targets, properties))
|
actions.append(ActionSpecs(action_type, targets, properties))
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
# Copyright 2017 - Nokia
|
||||||
|
#
|
||||||
|
# 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_log import log
|
||||||
|
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import WORKFLOW
|
||||||
|
from vitrage.evaluator.template_fields import TemplateFields
|
||||||
|
from vitrage.evaluator.template_validation.content.base import \
|
||||||
|
ActionValidator
|
||||||
|
from vitrage.evaluator.template_validation.content.base import \
|
||||||
|
get_content_correct_result
|
||||||
|
from vitrage.evaluator.template_validation.content.base import \
|
||||||
|
get_content_fault_result
|
||||||
|
from vitrage.evaluator.template_validation.status_messages import status_msgs
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ExecuteMistralValidator(ActionValidator):
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def validate(action, definitions_index):
|
||||||
|
properties = action[TemplateFields.PROPERTIES]
|
||||||
|
|
||||||
|
if WORKFLOW not in properties or not properties[WORKFLOW]:
|
||||||
|
LOG.error('%s status code: %s' % (status_msgs[133], 133))
|
||||||
|
return get_content_fault_result(133)
|
||||||
|
|
||||||
|
return get_content_correct_result()
|
@ -62,8 +62,8 @@ status_msgs = {
|
|||||||
'{actions}'.format(actions=action_types),
|
'{actions}'.format(actions=action_types),
|
||||||
121: 'At least one action must be defined.',
|
121: 'At least one action must be defined.',
|
||||||
122: 'Action field is required.',
|
122: 'Action field is required.',
|
||||||
123: 'Relationship definition must contain action_type field.',
|
123: 'Action definition must contain action_type field.',
|
||||||
124: 'Relationship definition must contain action_target field.',
|
124: 'Action definition must contain action_target field.',
|
||||||
125: 'raise_alarm action must contain alarm_name field in properties '
|
125: 'raise_alarm action must contain alarm_name field in properties '
|
||||||
'block.',
|
'block.',
|
||||||
126: 'raise_alarm action must contain severity field in properties block.',
|
126: 'raise_alarm action must contain severity field in properties block.',
|
||||||
@ -74,6 +74,8 @@ status_msgs = {
|
|||||||
'in target_action block.',
|
'in target_action block.',
|
||||||
131: 'mark_down action must contain \'target\' field in'
|
131: 'mark_down action must contain \'target\' field in'
|
||||||
' \'target_action\' block.',
|
' \'target_action\' block.',
|
||||||
132: 'add_causal_relationship action requires action_target to be ALARM'
|
132: 'add_causal_relationship action requires action_target to be ALARM',
|
||||||
|
133: 'execute_mistral action must contain workflow field in properties '
|
||||||
|
'block'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,10 @@ from oslo_utils import timeutils
|
|||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
from oslotest import base
|
from oslotest import base
|
||||||
import sys
|
import sys
|
||||||
|
from testtools.matchers import HasLength
|
||||||
|
|
||||||
|
|
||||||
|
IsEmpty = lambda: HasLength(0)
|
||||||
|
|
||||||
|
|
||||||
class BaseTest(base.BaseTestCase):
|
class BaseTest(base.BaseTestCase):
|
||||||
|
70
vitrage/tests/unit/evaluator/recipes/test_execute_mistral.py
Normal file
70
vitrage/tests/unit/evaluator/recipes/test_execute_mistral.py
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Copyright 2017 - Nokia
|
||||||
|
#
|
||||||
|
# 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 testtools.matchers import HasLength
|
||||||
|
from vitrage.evaluator.actions.base import ActionType
|
||||||
|
from vitrage.evaluator.actions.recipes.action_steps import EXECUTE_EXTERNAL
|
||||||
|
from vitrage.evaluator.actions.recipes.action_steps import EXECUTION_ENGINE
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import ExecuteMistral
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import MISTRAL
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import WORKFLOW
|
||||||
|
from vitrage.evaluator.template_data import ActionSpecs
|
||||||
|
from vitrage.tests.base import BaseTest
|
||||||
|
from vitrage.tests.base import IsEmpty
|
||||||
|
|
||||||
|
|
||||||
|
class RaiseAlarmRecipeTest(BaseTest):
|
||||||
|
|
||||||
|
# noinspection PyPep8Naming
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.props = {EXECUTION_ENGINE: MISTRAL,
|
||||||
|
WORKFLOW: 'wf_4',
|
||||||
|
'host': 'host5',
|
||||||
|
'state': 'ok'}
|
||||||
|
cls.action_spec = ActionSpecs(ActionType.EXECUTE_MISTRAL,
|
||||||
|
{},
|
||||||
|
cls.props)
|
||||||
|
|
||||||
|
def test_get_do_recipe(self):
|
||||||
|
|
||||||
|
# Test Action
|
||||||
|
action_steps = ExecuteMistral.get_do_recipe(self.action_spec)
|
||||||
|
|
||||||
|
# Test Assertions
|
||||||
|
|
||||||
|
# expecting for one step: [execute_external]
|
||||||
|
self.assertThat(action_steps, HasLength(1))
|
||||||
|
|
||||||
|
self.assertEqual(EXECUTE_EXTERNAL, action_steps[0].type)
|
||||||
|
execute_external_step_params = action_steps[0].params
|
||||||
|
self.assertIsNotNone(execute_external_step_params)
|
||||||
|
self.assertLessEqual(2, len(execute_external_step_params))
|
||||||
|
|
||||||
|
execution_engine = execute_external_step_params[EXECUTION_ENGINE]
|
||||||
|
self.assertEqual(self.props[EXECUTION_ENGINE], execution_engine)
|
||||||
|
|
||||||
|
workflow = execute_external_step_params[WORKFLOW]
|
||||||
|
self.assertEqual(self.props[WORKFLOW], workflow)
|
||||||
|
|
||||||
|
def test_get_undo_recipe(self):
|
||||||
|
|
||||||
|
# Test Action
|
||||||
|
action_steps = ExecuteMistral.get_undo_recipe(self.action_spec)
|
||||||
|
|
||||||
|
# Test Assertions
|
||||||
|
|
||||||
|
# expecting for zero steps (no undo for this action)
|
||||||
|
self.assertThat(action_steps, IsEmpty())
|
@ -0,0 +1,99 @@
|
|||||||
|
# Copyright 2017 - Nokia
|
||||||
|
#
|
||||||
|
# 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 vitrage.evaluator.actions.base import ActionType
|
||||||
|
from vitrage.evaluator.actions.recipes.execute_mistral import WORKFLOW
|
||||||
|
from vitrage.evaluator.template_fields import TemplateFields
|
||||||
|
from vitrage.evaluator.template_validation.content.execute_mistral_validator \
|
||||||
|
import ExecuteMistralValidator
|
||||||
|
from vitrage.tests.unit.evaluator.template_validation.content.base import \
|
||||||
|
ActionValidatorTest
|
||||||
|
from vitrage.tests.unit.evaluator.template_validation.content.base import \
|
||||||
|
DEFINITIONS_INDEX_MOCK
|
||||||
|
|
||||||
|
|
||||||
|
class ExecuteMistralValidatorTest(ActionValidatorTest):
|
||||||
|
|
||||||
|
def test_validate_execute_mistral_action(self):
|
||||||
|
|
||||||
|
self._validate_action(
|
||||||
|
self._create_execute_mistral_action('wf_1', 'host_2', 'down'),
|
||||||
|
ExecuteMistralValidator.validate
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_validate_execute_mistral_action_without_workflow(self):
|
||||||
|
|
||||||
|
# Test setup
|
||||||
|
idx = DEFINITIONS_INDEX_MOCK.copy()
|
||||||
|
action = self._create_execute_mistral_action('wf_1', 'host_2', 'down')
|
||||||
|
action[TemplateFields.PROPERTIES].pop(WORKFLOW)
|
||||||
|
|
||||||
|
# Test action
|
||||||
|
result = ExecuteMistralValidator.validate(action, idx)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self._assert_fault_result(result, 133)
|
||||||
|
|
||||||
|
def test_validate_execute_mistral_action_with_empty_workflow(self):
|
||||||
|
|
||||||
|
# Test setup
|
||||||
|
idx = DEFINITIONS_INDEX_MOCK.copy()
|
||||||
|
action = self._create_execute_mistral_action('', 'host_2', 'down')
|
||||||
|
|
||||||
|
# Test action
|
||||||
|
result = ExecuteMistralValidator.validate(action, idx)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self._assert_fault_result(result, 133)
|
||||||
|
|
||||||
|
def test_validate_execute_mistral_action_with_none_workflow(self):
|
||||||
|
|
||||||
|
# Test setup
|
||||||
|
idx = DEFINITIONS_INDEX_MOCK.copy()
|
||||||
|
action = self._create_execute_mistral_action(None, 'host_2', 'down')
|
||||||
|
|
||||||
|
# Test action
|
||||||
|
result = ExecuteMistralValidator.validate(action, idx)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self._assert_fault_result(result, 133)
|
||||||
|
|
||||||
|
def test_validate_execute_mistral_action_without_additional_params(self):
|
||||||
|
|
||||||
|
# Test setup - having only the 'workflow' param is a legal config
|
||||||
|
idx = DEFINITIONS_INDEX_MOCK.copy()
|
||||||
|
action = self._create_execute_mistral_action('wf_1', 'host_2', 'down')
|
||||||
|
action[TemplateFields.PROPERTIES].pop('host')
|
||||||
|
action[TemplateFields.PROPERTIES].pop('host_state')
|
||||||
|
|
||||||
|
# Test action
|
||||||
|
result = ExecuteMistralValidator.validate(action, idx)
|
||||||
|
|
||||||
|
# Test assertions
|
||||||
|
self._assert_correct_result(result)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _create_execute_mistral_action(workflow, host, host_state):
|
||||||
|
|
||||||
|
properties = {
|
||||||
|
WORKFLOW: workflow,
|
||||||
|
'host': host,
|
||||||
|
'host_state': host_state
|
||||||
|
}
|
||||||
|
action = {
|
||||||
|
TemplateFields.ACTION_TYPE: ActionType.EXECUTE_MISTRAL,
|
||||||
|
TemplateFields.PROPERTIES: properties
|
||||||
|
}
|
||||||
|
|
||||||
|
return action
|
Loading…
x
Reference in New Issue
Block a user