Skip to content

Commit f1ca675

Browse files
authored
Merge pull request #60 from eclipse-ankaios/59_unify_sdks
Unify the SDKs
2 parents 2f19187 + 16f3e7f commit f1ca675

File tree

14 files changed

+396
-484
lines changed

14 files changed

+396
-484
lines changed

ankaios_sdk/_components/complete_state.py

Lines changed: 94 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,16 @@
3030
3131
complete_state = CompleteState()
3232
33-
- Get the API version of the complete state:
33+
- Create a CompleteState instance from a Manifest:
3434
.. code-block:: python
3535
36-
api_version = complete_state.get_api_version()
36+
manifest = Manifest()
37+
complete_state = CompleteState(manifest=manifest)
3738
38-
- Add a workload to the complete state:
39+
- Get the API version of the complete state:
3940
.. code-block:: python
4041
41-
complete_state.add_workload(workload)
42+
api_version = complete_state.get_api_version()
4243
4344
- Get a workload from the complete state:
4445
.. code-block:: python
@@ -59,11 +60,6 @@
5960
.. code-block:: python
6061
6162
workload_states = complete_state.get_workload_states()
62-
63-
- Create a CompleteState instance from a Manifest:
64-
.. code-block:: python
65-
66-
complete_state = CompleteState.from_manifest(manifest)
6763
"""
6864

6965
__all__ = ["CompleteState"]
@@ -73,22 +69,64 @@
7369
from .workload import Workload
7470
from .workload_state import WorkloadStateCollection
7571
from .manifest import Manifest
76-
from ..utils import SUPPORTED_API_VERSION
72+
from ..utils import SUPPORTED_API_VERSION, _to_config_item, get_logger
73+
74+
75+
logger = get_logger()
7776

7877

7978
class CompleteState:
8079
"""
8180
A class to represent the complete state.
8281
"""
83-
def __init__(self) -> None:
82+
def __init__(self,
83+
manifest: Manifest = None,
84+
configs: dict = None,
85+
workloads: list[Workload] = None,
86+
_proto: _ank_base.CompleteState = None
87+
) -> None:
8488
"""
85-
Initializes an empty CompleteState instance with the given API version.
89+
Initializes a CompleteState instance with the provided data.
90+
91+
Args:
92+
manifest (Manifest): The manifest to initialize the complete state.
93+
configs (dict): The configurations to set in the complete state.
94+
workloads (list[Workload]): The workloads to set
95+
in the complete state.
96+
_proto (_ank_base.CompleteState): The proto message to initialize
97+
the complete state.
8698
"""
8799
self._complete_state = _ank_base.CompleteState()
88100
self._set_api_version(SUPPORTED_API_VERSION)
89-
self._workloads: list[Workload] = []
90-
self._workload_state_collection = WorkloadStateCollection()
91-
self._configs = {}
101+
if _proto:
102+
self._complete_state = _proto
103+
logger.debug(
104+
"CompleteState initialized from proto message"
105+
)
106+
return
107+
if manifest:
108+
self._complete_state.desiredState.CopyFrom(
109+
manifest._to_desired_state()
110+
)
111+
logger.debug(
112+
"CompleteState initialized from manifest"
113+
)
114+
return
115+
if configs:
116+
self.set_configs(configs)
117+
logger.debug(
118+
"CompleteState initialized from configs"
119+
)
120+
return
121+
if workloads:
122+
self._complete_state.desiredState.workloads.workloads.clear()
123+
for workload in workloads:
124+
self._complete_state.desiredState.workloads.workloads[
125+
workload.name].CopyFrom(workload._to_proto())
126+
logger.debug(
127+
"CompleteState initialized from workloads"
128+
)
129+
return
92130

93131
def __str__(self) -> str:
94132
"""
@@ -117,17 +155,6 @@ def get_api_version(self) -> str:
117155
"""
118156
return str(self._complete_state.desiredState.apiVersion)
119157

120-
def add_workload(self, workload: Workload) -> None:
121-
"""
122-
Adds a workload to the complete state.
123-
124-
Args:
125-
workload (Workload): The workload to add.
126-
"""
127-
self._workloads.append(workload)
128-
self._complete_state.desiredState.workloads.\
129-
workloads[workload.name].CopyFrom(workload._to_proto())
130-
131158
def get_workload(self, workload_name: str) -> Workload:
132159
"""
133160
Gets a workload from the complete state by its name.
@@ -139,9 +166,13 @@ def get_workload(self, workload_name: str) -> Workload:
139166
Workload: The workload with the specified name,
140167
or None if not found.
141168
"""
142-
for wl in self._workloads:
143-
if wl.name == workload_name:
144-
return wl
169+
if workload_name in self._complete_state. \
170+
desiredState.workloads.workloads.keys():
171+
proto_workload = self._complete_state. \
172+
desiredState.workloads.workloads[workload_name]
173+
workload = Workload(workload_name)
174+
workload._from_proto(proto_workload)
175+
return workload
145176
return None
146177

147178
def get_workloads(self) -> list[Workload]:
@@ -151,7 +182,13 @@ def get_workloads(self) -> list[Workload]:
151182
Returns:
152183
list[Workload]: A list of workloads in the complete state.
153184
"""
154-
return self._workloads
185+
workloads = []
186+
for wl_name, proto_workload in self._complete_state. \
187+
desiredState.workloads.workloads.items():
188+
workload = Workload(wl_name)
189+
workload._from_proto(proto_workload)
190+
workloads.append(workload)
191+
return workloads
155192

156193
def get_workload_states(self) -> WorkloadStateCollection:
157194
"""
@@ -160,7 +197,11 @@ def get_workload_states(self) -> WorkloadStateCollection:
160197
Returns:
161198
WorkloadStateCollection: The collection of workload states.
162199
"""
163-
return self._workload_state_collection
200+
workload_state_collection = WorkloadStateCollection()
201+
workload_state_collection._from_proto(
202+
self._complete_state.workloadStates
203+
)
204+
return workload_state_collection
164205

165206
def get_agents(self) -> dict[str, dict]:
166207
"""
@@ -184,23 +225,8 @@ def set_configs(self, configs: dict) -> None:
184225
Args:
185226
configs (dict): The configurations to set in the complete state.
186227
"""
187-
def _to_config_item(item: Union[str, list, dict]
188-
) -> _ank_base.ConfigItem:
189-
config_item = _ank_base.ConfigItem()
190-
if isinstance(item, str):
191-
config_item.String = item
192-
elif isinstance(item, list):
193-
for value in [_to_config_item(value) for value in item]:
194-
config_item.array.values.append(value)
195-
elif isinstance(item, dict):
196-
for key, value in item.items():
197-
config_item.object.fields[key]. \
198-
CopyFrom(_to_config_item(value))
199-
return config_item
200-
201-
self._configs = configs
202228
self._complete_state.desiredState.configs.configs.clear()
203-
for key, value in self._configs.items():
229+
for key, value in configs.items():
204230
self._complete_state.desiredState.configs.configs[key].CopyFrom(
205231
_to_config_item(value)
206232
)
@@ -212,33 +238,22 @@ def get_configs(self) -> dict:
212238
Returns:
213239
dict: The configurations from the complete state
214240
"""
215-
return self._configs
216-
217-
@staticmethod
218-
def from_manifest(manifest: Manifest) -> 'CompleteState':
219-
"""
220-
Creates a CompleteState instance from a Manifest.
221-
222-
Args:
223-
manifest (Manifest): The manifest to create the
224-
complete state from.
225-
"""
226-
state = CompleteState()
227-
state._complete_state = _ank_base.CompleteState()
228-
dict_state = manifest._manifest
229-
state._set_api_version(
230-
dict_state.get("apiVersion", state.get_api_version())
231-
)
232-
state._workloads = []
233-
if dict_state.get("workloads") is not None:
234-
for workload_name, workload_dict in \
235-
dict_state.get("workloads").items():
236-
state.add_workload(
237-
Workload._from_dict(workload_name, workload_dict)
238-
)
239-
if dict_state.get("configs") is not None:
240-
state.set_configs(dict_state.get("configs"))
241-
return state
241+
def _from_config_item(item: _ank_base.ConfigItem
242+
) -> Union[str, list, dict]:
243+
if item.HasField("String"):
244+
return item.String
245+
if item.HasField("array"):
246+
return [_from_config_item(value)
247+
for value in item.array.values]
248+
if item.HasField("object"):
249+
return {key: _from_config_item(value)
250+
for key, value in item.object.fields.items()}
251+
return None # pragma: no cover
252+
configs = {}
253+
for key, value in self._complete_state.desiredState. \
254+
configs.configs.items():
255+
configs[key] = _from_config_item(value)
256+
return configs
242257

243258
def to_dict(self) -> dict:
244259
"""
@@ -251,15 +266,15 @@ def to_dict(self) -> dict:
251266
"desired_state": {
252267
"api_version": self.get_api_version(),
253268
"workloads": {},
254-
"configs": self._configs
269+
"configs": self.get_configs()
255270
},
256271
"workload_states": {},
257272
"agents": {}
258273
}
259-
for wl in self._workloads:
260-
data["desired_state"]["workloads"][wl.name] = \
261-
wl.to_dict()
262-
wl_states = self._workload_state_collection.get_as_dict()
274+
for workload in self.get_workloads():
275+
data["desired_state"]["workloads"][workload.name] = \
276+
workload.to_dict()
277+
wl_states = self.get_workload_states().get_as_dict()
263278
for agent_name, exec_states in wl_states.items():
264279
data["workload_states"][agent_name] = {}
265280
for workload_name, exec_states_id in exec_states.items():
@@ -279,39 +294,3 @@ def _to_proto(self) -> _ank_base.CompleteState:
279294
the complete state.
280295
"""
281296
return self._complete_state
282-
283-
def _from_proto(self, proto: _ank_base.CompleteState) -> None:
284-
"""
285-
Converts the proto message to a CompleteState object.
286-
287-
Args:
288-
proto (_ank_base.CompleteState): The protobuf message representing
289-
the complete state.
290-
"""
291-
def _from_config_item(item: _ank_base.ConfigItem
292-
) -> Union[str, list, dict]:
293-
if item.HasField("String"):
294-
return item.String
295-
if item.HasField("array"):
296-
return [_from_config_item(value)
297-
for value in item.array.values]
298-
if item.HasField("object"):
299-
return {key: _from_config_item(value)
300-
for key, value in item.object.fields.items()}
301-
return None # pragma: no cover
302-
303-
self._complete_state = proto
304-
self._workloads = []
305-
for workload_name, proto_workload in self._complete_state. \
306-
desiredState.workloads.workloads.items():
307-
workload = Workload(workload_name)
308-
workload._from_proto(proto_workload)
309-
self._workloads.append(workload)
310-
self._workload_state_collection._from_proto(
311-
self._complete_state.workloadStates
312-
)
313-
configs = {}
314-
for key, value in self._complete_state.desiredState. \
315-
configs.configs.items():
316-
configs[key] = _from_config_item(value)
317-
self.set_configs(configs)

ankaios_sdk/_components/control_interface.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,7 @@ class ControlInterface:
9797
"(str): The base path for the Ankaios control interface."
9898

9999
def __init__(self,
100-
add_response_callback: Callable,
101-
state_changed_callback: Callable
100+
add_response_callback: Callable
102101
) -> None:
103102
"""
104103
Initialize the ControlInterface object. This is used
@@ -119,20 +118,9 @@ def __init__(self,
119118
self._disconnect_event = threading.Event()
120119

121120
self._add_response_callback = add_response_callback
122-
self._state_changed_callback = state_changed_callback
123121

124122
self._logger = get_logger()
125123

126-
@property
127-
def state(self) -> ControlInterfaceState:
128-
"""
129-
Returns the current state of the control interface.
130-
131-
Returns:
132-
ControlInterfaceState: The state of the control interface.
133-
"""
134-
return self._state
135-
136124
def connect(self) -> None:
137125
"""
138126
Connect to the control interface by starting to read
@@ -225,7 +213,12 @@ def change_state(
225213
self._logger.debug("State CONNECTION_CLOSED is unrecoverable.")
226214
return
227215
self._state = state
228-
self._state_changed_callback(state, info)
216+
if info is None:
217+
self._logger.debug("State changed to %s.", state)
218+
else:
219+
self._logger.debug(
220+
"State changed to %s: %s", state, info
221+
)
229222

230223
# pylint: disable=too-many-statements, too-many-branches
231224
def _read_from_control_interface(self) -> None:
@@ -327,7 +320,7 @@ def _agent_gone_routine(self) -> None:
327320
until the agent is connected.
328321
"""
329322
agent_reconnect_interval = 1 # seconds
330-
while self.state == ControlInterfaceState.AGENT_DISCONNECTED:
323+
while self._state == ControlInterfaceState.AGENT_DISCONNECTED:
331324
try:
332325
self._send_initial_hello()
333326
except BrokenPipeError as _:

0 commit comments

Comments
 (0)