fixed config service to leverage validation_timer properly, added unit tests for config service base class

This commit is contained in:
Blake Harnden 2020-01-27 10:57:16 -08:00
parent 80073dd8c8
commit 09aa882017
2 changed files with 310 additions and 2 deletions

View file

@ -140,7 +140,7 @@ class ConfigService(abc.ABC):
self.run_startup(wait) self.run_startup(wait)
if not wait: if not wait:
if self.validation_mode == ConfigServiceMode.TIMER: if self.validation_mode == ConfigServiceMode.TIMER:
time.sleep(self.validation_timer) self.wait_validation()
else: else:
self.run_validation() self.run_validation()
@ -275,6 +275,14 @@ class ConfigService(abc.ABC):
f"node({self.node.name}) service({self.name}) failed startup: {e}" f"node({self.node.name}) service({self.name}) failed startup: {e}"
) )
def wait_validation(self) -> None:
"""
Waits for a period of time to consider service started successfully.
:return: nothing
"""
time.sleep(self.validation_timer)
def run_validation(self) -> None: def run_validation(self) -> None:
""" """
Runs validation commands for service on node. Runs validation commands for service on node.
@ -298,7 +306,7 @@ class ConfigService(abc.ABC):
) )
time.sleep(self.validation_period) time.sleep(self.validation_period)
if cmds and time.monotonic() - start > 0: if cmds and time.monotonic() - start > self.validation_timer:
raise ConfigServiceBootError( raise ConfigServiceBootError(
f"node({self.node.name}) service({self.name}) failed to validate" f"node({self.node.name}) service({self.name}) failed to validate"
) )

View file

@ -0,0 +1,300 @@
from unittest import mock
import pytest
from core.config import Configuration
from core.configservice.base import (
ConfigService,
ConfigServiceBootError,
ConfigServiceMode,
)
from core.emulator.enumerations import ConfigDataTypes
from core.errors import CoreCommandError, CoreError
TEMPLATE_TEXT = "echo hello"
class MyService(ConfigService):
name = "MyService"
group = "MyGroup"
directories = ["/usr/local/lib"]
files = ["test.sh"]
executables = []
dependencies = []
startup = [f"sh {files[0]}"]
validate = [f"pidof {files[0]}"]
shutdown = [f"pkill {files[0]}"]
validation_mode = ConfigServiceMode.BLOCKING
default_configs = [
Configuration(_id="value1", _type=ConfigDataTypes.STRING, label="Text"),
Configuration(_id="value2", _type=ConfigDataTypes.BOOL, label="Boolean"),
Configuration(
_id="value3",
_type=ConfigDataTypes.STRING,
label="Multiple Choice",
options=["value1", "value2", "value3"],
),
]
modes = {
"mode1": {"value1": "value1", "value2": "0", "value3": "value2"},
"mode2": {"value1": "value2", "value2": "1", "value3": "value3"},
"mode3": {"value1": "value3", "value2": "0", "value3": "value1"},
}
def get_text_template(self, name: str) -> str:
return TEMPLATE_TEXT
class TestConfigServices:
def test_set_template(self):
# given
node = mock.MagicMock()
text = "echo custom"
service = MyService(node)
# when
service.set_template(MyService.files[0], text)
# then
assert MyService.files[0] in service.custom_templates
assert service.custom_templates[MyService.files[0]] == text
def test_create_directories(self):
# given
node = mock.MagicMock()
service = MyService(node)
# when
service.create_dirs()
# then
node.privatedir.assert_called_with(MyService.directories[0])
def test_create_files_custom(self):
# given
node = mock.MagicMock()
service = MyService(node)
text = "echo custom"
service.set_template(MyService.files[0], text)
# when
service.create_files()
# then
node.nodefile.assert_called_with(MyService.files[0], text)
def test_create_files_text(self):
# given
node = mock.MagicMock()
service = MyService(node)
# when
service.create_files()
# then
node.nodefile.assert_called_with(MyService.files[0], TEMPLATE_TEXT)
def test_run_startup(self):
# given
node = mock.MagicMock()
wait = True
service = MyService(node)
# when
service.run_startup(wait=wait)
# then
node.cmd.assert_called_with(MyService.startup[0], wait=wait)
def test_run_startup_exception(self):
# given
node = mock.MagicMock()
node.cmd.side_effect = CoreCommandError(1, "error")
service = MyService(node)
# when
with pytest.raises(ConfigServiceBootError):
service.run_startup(wait=True)
def test_shutdown(self):
# given
node = mock.MagicMock()
service = MyService(node)
# when
service.stop()
# then
node.cmd.assert_called_with(MyService.shutdown[0])
def test_run_validation(self):
# given
node = mock.MagicMock()
service = MyService(node)
# when
service.run_validation()
# then
node.cmd.assert_called_with(MyService.validate[0])
def test_run_validation_timer(self):
# given
node = mock.MagicMock()
service = MyService(node)
service.validation_mode = ConfigServiceMode.TIMER
service.validation_timer = 0
# when
service.run_validation()
# then
node.cmd.assert_called_with(MyService.validate[0])
def test_run_validation_timer_exception(self):
# given
node = mock.MagicMock()
node.cmd.side_effect = CoreCommandError(1, "error")
service = MyService(node)
service.validation_mode = ConfigServiceMode.TIMER
service.validation_period = 0
service.validation_timer = 0
# when
with pytest.raises(ConfigServiceBootError):
service.run_validation()
def test_run_validation_non_blocking(self):
# given
node = mock.MagicMock()
service = MyService(node)
service.validation_mode = ConfigServiceMode.NON_BLOCKING
service.validation_period = 0
service.validation_timer = 0
# when
service.run_validation()
# then
node.cmd.assert_called_with(MyService.validate[0])
def test_run_validation_non_blocking_exception(self):
# given
node = mock.MagicMock()
node.cmd.side_effect = CoreCommandError(1, "error")
service = MyService(node)
service.validation_mode = ConfigServiceMode.NON_BLOCKING
service.validation_period = 0
service.validation_timer = 0
# when
with pytest.raises(ConfigServiceBootError):
service.run_validation()
def test_render_config(self):
# given
node = mock.MagicMock()
service = MyService(node)
# when
config = service.render_config()
# then
assert config == {"value1": "", "value2": "", "value3": ""}
def test_render_config_custom(self):
# given
node = mock.MagicMock()
service = MyService(node)
custom_config = {"value1": "1", "value2": "2", "value3": "3"}
service.set_config(custom_config)
# when
config = service.render_config()
# then
assert config == custom_config
def test_set_config(self):
# given
node = mock.MagicMock()
service = MyService(node)
custom_config = {"value1": "1", "value2": "2", "value3": "3"}
# when
service.set_config(custom_config)
# then
assert service.custom_config == custom_config
def test_set_config_exception(self):
# given
node = mock.MagicMock()
service = MyService(node)
custom_config = {"value4": "1"}
# when
with pytest.raises(CoreError):
service.set_config(custom_config)
def test_start_blocking(self):
# given
node = mock.MagicMock()
service = MyService(node)
service.create_dirs = mock.MagicMock()
service.create_files = mock.MagicMock()
service.run_startup = mock.MagicMock()
service.run_validation = mock.MagicMock()
service.wait_validation = mock.MagicMock()
# when
service.start()
# then
service.create_files.assert_called_once()
service.create_dirs.assert_called_once()
service.run_startup.assert_called_once()
service.run_validation.assert_not_called()
service.wait_validation.assert_not_called()
def test_start_timer(self):
# given
node = mock.MagicMock()
service = MyService(node)
service.validation_mode = ConfigServiceMode.TIMER
service.create_dirs = mock.MagicMock()
service.create_files = mock.MagicMock()
service.run_startup = mock.MagicMock()
service.run_validation = mock.MagicMock()
service.wait_validation = mock.MagicMock()
# when
service.start()
# then
service.create_files.assert_called_once()
service.create_dirs.assert_called_once()
service.run_startup.assert_called_once()
service.run_validation.assert_not_called()
service.wait_validation.assert_called_once()
def test_start_non_blocking(self):
# given
node = mock.MagicMock()
service = MyService(node)
service.validation_mode = ConfigServiceMode.NON_BLOCKING
service.create_dirs = mock.MagicMock()
service.create_files = mock.MagicMock()
service.run_startup = mock.MagicMock()
service.run_validation = mock.MagicMock()
service.wait_validation = mock.MagicMock()
# when
service.start()
# then
service.create_files.assert_called_once()
service.create_dirs.assert_called_once()
service.run_startup.assert_called_once()
service.run_validation.assert_called_once()
service.wait_validation.assert_not_called()