11"""Provide necessary information that is needed for a specific test."""
2- from typing import Any , Callable , Optional
2+ import pathlib
3+ from typing import Any , Callable , Optional , Dict , Union
34
5+ from nornir import InitNornir
46from nornir .core import Nornir
57from nornir .core .task import AggregatedResult
68
79from nuts .helpers .errors import NutsSetupError
10+ from nuts .helpers .result import NutsResult
11+
12+
13+ _TransformedResult = Dict [str , Any ]
814
915
1016class NutsContext :
@@ -16,6 +22,11 @@ class NutsContext:
1622
1723 def __init__ (self , nuts_parameters : Any = None ):
1824 self .nuts_parameters = nuts_parameters or {}
25+ self ._cached_result : Optional [_TransformedResult ] = None
26+
27+ def initialize (self ) -> None :
28+ """Initialize dependencies for this context after it has been created."""
29+ pass
1930
2031 def nuts_arguments (self ) -> dict :
2132 """
@@ -30,6 +41,30 @@ def nuts_arguments(self) -> dict:
3041 test_execution = self .nuts_parameters .get ("test_execution" , None )
3142 return {** (test_execution if test_execution is not None else {})}
3243
44+ def general_result (self ) -> Any :
45+ """
46+ :return: raw, unprocessed result
47+ """
48+ raise NotImplementedError
49+
50+ def transform_result (self , general_result : Any ) -> _TransformedResult :
51+ """
52+ :param general_result: raw result
53+ :return: processed result ready to be passed to a test
54+ """
55+ raise NotImplementedError
56+
57+ @property
58+ def transformed_result (self ) -> _TransformedResult :
59+ """
60+ The (processed) results of the network task, ready to be passed on to a test's fixture.
61+ The results are cached, so that general_result does not need to be called multiple times as it might
62+ access the network.
63+ """
64+ if self ._cached_result is None :
65+ self ._cached_result = self .transform_result (self .general_result ())
66+ return self ._cached_result
67+
3368
3469class NornirNutsContext (NutsContext ):
3570 """
@@ -41,11 +76,20 @@ class NornirNutsContext(NutsContext):
4176
4277 """
4378
79+ #: The path to a nornir configuration file.
80+ #: https://nornir.readthedocs.io/en/stable/configuration/index.html
81+ NORNIR_CONFIG_FILE = pathlib .Path ("nr-config.yaml" )
82+
4483 def __init__ (self , nuts_parameters : Any = None ):
4584 super ().__init__ (nuts_parameters )
46- self ._transformed_result = None
4785 self .nornir : Optional [Nornir ] = None
4886
87+ def initialize (self ) -> None :
88+ self .nornir = InitNornir (
89+ config_file = str (self .NORNIR_CONFIG_FILE ),
90+ logging = {"enabled" : False },
91+ )
92+
4993 def nuts_task (self ) -> Callable :
5094 """
5195 Returns the task that nornir should execute for the test module.
@@ -60,14 +104,14 @@ def nornir_filter(self):
60104 """
61105 return None
62106
63- def transform_result (self , general_result : AggregatedResult ) -> Any :
107+ def transform_result (self , general_result : AggregatedResult ) -> Dict [ str , Any ] :
64108 """
65109 Transforms the raw nornir result and wraps it into a `NutsResult`.
66110
67111 :param general_result: The raw answer as provided by nornir's executed task
68- :return: Usually a dict where keys are the hosts, values are a `NutsResult`
112+ :return: A dict where keys are the hosts, values are a `NutsResult`
69113 """
70- return general_result
114+ raise NotImplementedError
71115
72116 def general_result (self ) -> AggregatedResult :
73117 """
@@ -102,13 +146,3 @@ def teardown(self):
102146 Defines code which is executed after the nornir task.
103147 """
104148 pass
105-
106- def transformed_result (self ) -> Any :
107- """
108- The result from nornir's task, transformed to be passed on later to a test's fixture
109- called `single_result`.
110- :return: The transformed result
111- """
112- if not self ._transformed_result :
113- self ._transformed_result = self .transform_result (self .general_result ())
114- return self ._transformed_result
0 commit comments