-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
191 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from carnival.steps.step import Step, InlineStep | ||
|
||
|
||
__all__ = ( | ||
"Step", | ||
"InlineStep", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
""" | ||
Кеширование валидаторов для Steps | ||
Кеширует значение по Type[Step], Host, fact_id:str(задается в валидаторе) | ||
""" | ||
|
||
import typing | ||
|
||
if typing.TYPE_CHECKING: | ||
from carnival import Host | ||
from carnival.steps.validators import StepValidatorBase | ||
|
||
|
||
StepValidatorBaseT = typing.TypeVar("StepValidatorBaseT", bound="StepValidatorBase") | ||
__vc: typing.Dict[str, typing.Optional[str]] = {} | ||
|
||
|
||
def __build_vc_key(step_class: typing.Type[StepValidatorBaseT], host: "Host", fact_id: str) -> str: | ||
from carnival.utils import get_class_full_name | ||
return f"{get_class_full_name(step_class)}::{host.addr}::{fact_id}" | ||
|
||
|
||
def try_get( | ||
step_class: typing.Type[StepValidatorBaseT], | ||
host: "Host", | ||
fact_id: str, | ||
) -> typing.Tuple[bool, typing.Optional[str]]: | ||
global __vc | ||
|
||
return ( | ||
__build_vc_key(step_class=step_class, host=host, fact_id=fact_id) in __vc, | ||
__vc.get( | ||
__build_vc_key(step_class=step_class, host=host, fact_id=fact_id), | ||
None, | ||
) | ||
) | ||
|
||
|
||
def set(step_class: typing.Type[StepValidatorBaseT], host: "Host", fact_id: str, val: typing.Optional[str]) -> None: | ||
global __vc | ||
cachekey = __build_vc_key(step_class=step_class, host=host, fact_id=fact_id) | ||
|
||
is_exist, *_ = try_get(step_class=step_class, host=host, fact_id=fact_id) | ||
if is_exist: | ||
raise ValueError(f"Broken cache: '{cachekey}' already exist!") | ||
|
||
__vc[cachekey] = val |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import typing | ||
import abc | ||
|
||
from carnival import cmd | ||
from carnival.steps import _validator_cache | ||
from carnival.templates import render | ||
|
||
from jinja2.exceptions import UndefinedError, TemplateNotFound, TemplateSyntaxError | ||
|
||
|
||
if typing.TYPE_CHECKING: | ||
from carnival import Connection | ||
from carnival.steps.step import Step | ||
|
||
|
||
class StepValidatorBase: | ||
def __init__(self, step: "Step"): | ||
self.step = step | ||
|
||
@abc.abstractmethod | ||
def validate(self, c: "Connection") -> typing.Optional[str]: | ||
raise NotImplementedError | ||
|
||
|
||
class InlineValidator(StepValidatorBase): | ||
def __init__( | ||
self, | ||
if_err_true_fn: typing.Callable[["Connection"], bool], | ||
error_message: str, | ||
fact_id_for_caching: typing.Optional[str] = None, | ||
): | ||
self.if_err_true_fn = if_err_true_fn | ||
self.error_message = error_message | ||
self.fact_id_for_caching = fact_id_for_caching | ||
|
||
def validate(self, c: "Connection") -> typing.Optional[str]: | ||
if self.fact_id_for_caching is not None: | ||
is_exist, val = _validator_cache.try_get(self.__class__, c.host, self.fact_id_for_caching) | ||
if is_exist: | ||
return val | ||
|
||
val = None | ||
if self.if_err_true_fn(c): | ||
val = self.error_message | ||
|
||
if self.fact_id_for_caching is not None: | ||
_validator_cache.set(self.__class__, c.host, self.fact_id_for_caching, val=val) | ||
return val | ||
|
||
|
||
class CommandRequiredValidator(StepValidatorBase): | ||
def __init__(self, command: str) -> None: | ||
self.command = command | ||
self.fact_id = f"path-{command}-required" | ||
|
||
def validate(self, c: "Connection") -> typing.Optional[str]: | ||
is_exist, val = _validator_cache.try_get(self.__class__, c.host, self.fact_id) | ||
|
||
if is_exist: | ||
return val | ||
|
||
val = None | ||
if not cmd.cli.is_cmd_exist(c, self.command): | ||
val = f"'{self.command}' is required" | ||
|
||
_validator_cache.set(self.__class__, c.host, self.fact_id, val=val) | ||
return val | ||
|
||
|
||
class TemplateValidator(StepValidatorBase): | ||
def __init__(self, template_path: str, context: typing.Dict[str, typing.Any]): | ||
self.template_path = template_path | ||
self.context = context | ||
|
||
def validate(self, c: "Connection") -> typing.Optional[str]: | ||
# TODO: more catch errors maybe? | ||
try: | ||
render(self.template_path, **self.context) | ||
except (UndefinedError, TemplateNotFound, TemplateSyntaxError) as ex: | ||
return f"{ex.__class__.__name__}: {ex}" | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +0,0 @@ | ||
from carnival import utils, LocalHost | ||
|
||
|
||
def test_log(capsys): | ||
utils.log("Hellotest", host=LocalHost()) | ||
captured = capsys.readouterr() | ||
assert captured.out == "💃💃💃 🖥 local> Hellotest\n" | ||