Skip to content

Commit 4b4236c

Browse files
committed
added components module
1 parent 9cb0cd1 commit 4b4236c

File tree

11 files changed

+133
-32
lines changed

11 files changed

+133
-32
lines changed

src/cloudshell/sandbox_rest/api.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@
1313
from tenacity import RetryError, retry, retry_if_result, stop_after_delay, wait_fixed
1414

1515
from cloudshell.sandbox_rest import exceptions, model
16-
from cloudshell.sandbox_rest.default_logger import set_up_default_logger
1716
from pydantic.main import ValidationError
1817

1918

20-
2119
@dataclass
2220
class CommandInputParam:
2321
"""
@@ -50,7 +48,7 @@ def __init__(
5048
show_insecure_warning=False
5149
):
5250
""" Login to api and store headers for future requests """
53-
self.logger = logger or set_up_default_logger()
51+
self.logger = logger
5452
super().__init__(host, username, password, token, logger, port, use_https, ssl_verify, proxies, show_insecure_warning)
5553
self.domain = domain
5654
self._base_uri = "/api"
@@ -243,7 +241,7 @@ def run_sandbox_command(
243241
max_polling_minutes: int = 20,
244242
polling_frequency_seconds: int = 10,
245243
polling_log_level: int = logging.DEBUG
246-
) -> model.EnvironmentCommandExecutionDetails:
244+
) -> model.SandboxCommandExecutionDetails:
247245
"""Run a sandbox level command"""
248246
self._validate_auth_header()
249247
uri = f"{self._v2_base_uri}/sandboxes/{sandbox_id}/commands/{command_name}/start"
@@ -253,7 +251,7 @@ def run_sandbox_command(
253251
response_dict = self.rest_service.request_post(uri, data).json()
254252
start_response = model.CommandStartResponse.dict_to_model(response_dict)
255253
model_wrapped_command_params = [model.CommandParameterNameValue(x.name, x.value) for x in params] if params else []
256-
command_context = model.CommandContextDetails(sandbox_id=sandbox_id,
254+
command_context = model.SandboxCommandContext(sandbox_id=sandbox_id,
257255
command_name=command_name,
258256
command_params=model_wrapped_command_params)
259257
if polling_execution:
@@ -264,13 +262,13 @@ def run_sandbox_command(
264262
else:
265263
execution_details = self.get_execution_details(start_response.executionId)
266264

267-
return model.EnvironmentCommandExecutionDetails(id=start_response.executionId,
268-
status=execution_details.status,
269-
supports_cancellation=execution_details.supports_cancellation,
270-
started=execution_details.started,
271-
ended=execution_details.ended,
272-
output=execution_details.output,
273-
command_context=command_context)
265+
return model.SandboxCommandExecutionDetails(id=start_response.executionId,
266+
status=execution_details.status,
267+
supports_cancellation=execution_details.supports_cancellation,
268+
started=execution_details.started,
269+
ended=execution_details.ended,
270+
output=execution_details.output,
271+
command_context=command_context)
274272

275273
def run_component_command(
276274
self,
@@ -294,11 +292,11 @@ def run_component_command(
294292
start_response = model.CommandStartResponse.dict_to_model(response_dict)
295293
component_details = self.get_sandbox_component_details(sandbox_id, component_id)
296294
model_wrapped_command_params = [model.CommandParameterNameValue(x.name, x.value) for x in params] if params else []
297-
command_context = model.ComponentCommandContextDetails(sandbox_id=sandbox_id,
298-
command_name=command_name,
299-
command_params=model_wrapped_command_params,
300-
component_name=component_details.name,
301-
component_id=component_details.id)
295+
command_context = model.ComponentCommandContext(sandbox_id=sandbox_id,
296+
command_name=command_name,
297+
command_params=model_wrapped_command_params,
298+
component_name=component_details.name,
299+
component_id=component_details.id)
302300
if polling_execution:
303301
execution_details = self.poll_command_execution(execution_id=start_response.executionId,
304302
max_polling_minutes=max_polling_minutes,
@@ -575,8 +573,8 @@ def poll_sandbox_teardown(
575573

576574
def poll_command_execution(self,
577575
execution_id: str,
578-
max_polling_minutes: int,
579-
polling_frequency_seconds: int,
576+
max_polling_minutes=10,
577+
polling_frequency_seconds=30,
580578
log_level=logging.DEBUG,
581579
) -> model.CommandExecutionDetails:
582580
""" Create blocking polling process """
Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,84 @@
11
"""
22
Component helpers for filtering and sorting the sandbox components
33
"""
4+
from enum import Enum
5+
from typing import List
6+
7+
from cloudshell.sandbox_rest import model
8+
from cloudshell.sandbox_rest.api import SandboxRestApiSession
9+
10+
11+
class ComponentTypes(str, Enum):
12+
app_type = "Application"
13+
resource_type = "Resource"
14+
service_type = "Service"
15+
16+
17+
class AppLifeCycleTypes(str, Enum):
18+
deployed = "Deployed"
19+
un_deployed = "Undeployed"
20+
21+
22+
class AttributeTypes(str, Enum):
23+
boolean = "boolean"
24+
password = "password"
25+
string = "string"
26+
numeric = "numeric"
427

528

629
class SandboxComponents:
7-
pass
30+
def __init__(self, components: List[model.SandboxComponentFull] = None):
31+
self.all_components = components or []
32+
33+
def refresh_components(self, api: SandboxRestApiSession, sandbox_id: str) -> None:
34+
self.all_components = api.get_sandbox_components(sandbox_id)
35+
36+
def _filter_components_by_type(self, component_type: ComponentTypes) -> List[model.SandboxComponentFull]:
37+
""" accepts both short info components and full info """
38+
return [component for component in self.all_components if component.component_type == component_type]
39+
40+
def _filter_app_by_lifecycle(self, lifecycle_type: AppLifeCycleTypes) -> List[model.SandboxComponentFull]:
41+
return [component for component in self.all_components if component.component_type == ComponentTypes.app_type
42+
and component.app_lifecycle == lifecycle_type]
43+
44+
@property
45+
def resources(self):
46+
return self._filter_components_by_type(ComponentTypes.service_type)
47+
48+
@property
49+
def services(self):
50+
return self._filter_components_by_type(ComponentTypes.service_type)
51+
52+
@property
53+
def deployed_apps(self):
54+
return self._filter_app_by_lifecycle(AppLifeCycleTypes.deployed)
55+
56+
@property
57+
def un_deployed_apps(self):
58+
return self._filter_app_by_lifecycle(AppLifeCycleTypes.un_deployed)
59+
60+
def filter_by_model(self, component_model: str) -> List[dict]:
61+
"""
62+
Component Model / Shell Template
63+
ex: 'Juniper JunOS Switch Shell 2G'
64+
"""
65+
return [component for component in self.all_components if component.component_type == component_model]
66+
67+
def filter_by_attr(self, attr_name: str, attr_val: str) -> List[model.SandboxComponentFull]:
68+
""" attr name is shell agnostic, no namespacing """
69+
components = []
70+
for component in self.all_components:
71+
for attr in component.attributes:
72+
if attr.name.endswith(attr_name) and attr.value == attr_val:
73+
components.append(component)
74+
return components
75+
76+
def filter_by_boolean_attr(self, attr_name: str) -> List[dict]:
77+
""" attr name is shell agnostic, no namespacing """
78+
components = []
79+
for component in self.all_components:
80+
for attr in component.attributes:
81+
if attr.type == AttributeTypes.boolean and attr.name.endswith(attr_name) and attr.value == "True":
82+
components.append(component)
83+
return components
84+

src/cloudshell/sandbox_rest/model.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,8 @@ class CommandParameterDetails(SandboxApiBaseModel):
214214

215215
@_basemodel_decorator
216216
class CommandParameterNameValue(SandboxApiBaseModel):
217-
name: Optional[str]
218-
value: Optional[str]
217+
name: str
218+
value: str
219219

220220

221221
@_basemodel_decorator
@@ -314,23 +314,23 @@ class StopSandboxResponse(SandboxApiBaseModel):
314314

315315

316316
@_basemodel_decorator
317-
class CommandContextDetails(SandboxApiBaseModel):
317+
class SandboxCommandContext(SandboxApiBaseModel):
318318
sandbox_id: Optional[str]
319319
command_name: Optional[str]
320320
command_params: Optional[List[CommandParameterNameValue]]
321321

322322

323323
@_basemodel_decorator
324-
class ComponentCommandContextDetails(CommandContextDetails):
324+
class ComponentCommandContext(SandboxCommandContext):
325325
component_name: Optional[str]
326326
component_id: Optional[str]
327327

328328

329329
@_basemodel_decorator
330-
class EnvironmentCommandExecutionDetails(CommandExecutionDetails):
331-
command_context: Optional[CommandContextDetails]
330+
class SandboxCommandExecutionDetails(CommandExecutionDetails):
331+
command_context: Optional[SandboxCommandContext]
332332

333333

334334
@_basemodel_decorator
335335
class ComponentCommandExecutionDetails(CommandExecutionDetails):
336-
command_context: Optional[ComponentCommandContextDetails]
336+
command_context: Optional[ComponentCommandContext]
Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
11
"""
22
Sandbox controller context manager to manage the lifecyle of setup and teardown
3+
- start sandbox on context enter, end sandbox on context exit
4+
- cache setup / teardown duration and errors
5+
- components object member
6+
- async commands executor member
37
"""
4-
8+
import logging
59

610
from cloudshell.sandbox_rest.api import SandboxRestApiSession
11+
from cloudshell.sandbox_rest.async_commands import AsyncCommandExecutor
12+
from cloudshell.sandbox_rest.components import SandboxComponents
13+
14+
15+
class SandboxStartRequest:
16+
pass
717

818

919
class SandboxControllerContext:
10-
def __init__(self, api: SandboxRestApiSession, sandbox_id: str = None):
20+
def __init__(self, api: SandboxRestApiSession, sandbox_request: SandboxStartRequest = None, sandbox_id: str = None,
21+
logger: logging.Logger = None):
1122
self.api = api
23+
self.sandbox_request = sandbox_request
1224
self.sandbox_id = sandbox_id
25+
self.logger = logger
26+
self.components = SandboxComponents()
27+
self.async_executor = AsyncCommandExecutor()
28+
self.setup_duration_seconds: int = None
29+
self.teardown_duration_seconds: int = None
30+
self.setup_errors = None
31+
self.teardown_errors = None
1332

1433
def __enter__(self):
1534
""" start sandbox """
@@ -18,3 +37,10 @@ def __enter__(self):
1837
def __exit__(self, exc_type, exc_val, exc_tb):
1938
""" end sandbox """
2039
return self
40+
41+
def refresh_components(self):
42+
self.components.refresh_components(self.api, self.sandbox_id)
43+
44+
45+
if __name__ == "__main__":
46+
controller = SandboxControllerContext()

0 commit comments

Comments
 (0)