holado 0.4.1__py3-none-any.whl → 0.4.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of holado might be problematic. Click here for more details.
- holado/common/handlers/object.py +6 -0
- {holado-0.4.1.dist-info → holado-0.4.2.dist-info}/METADATA +2 -1
- {holado-0.4.1.dist-info → holado-0.4.2.dist-info}/RECORD +42 -21
- holado_core/tools/abstracts/blocking_command_service.py +9 -1
- holado_django/__init__.py +31 -0
- holado_django/server/HOWTO.txt +27 -0
- holado_django/server/django_projects/rest_api/db.sqlite3 +0 -0
- holado_django/server/django_projects/rest_api/manage.py +22 -0
- holado_django/server/django_projects/rest_api/rest_api/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/admin.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/apps.py +9 -0
- holado_django/server/django_projects/rest_api/rest_api/application/migrations/__init__.py +0 -0
- holado_django/server/django_projects/rest_api/rest_api/application/models.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/tests.py +3 -0
- holado_django/server/django_projects/rest_api/rest_api/application/views.py +6 -0
- holado_django/server/django_projects/rest_api/rest_api/asgi.py +16 -0
- holado_django/server/django_projects/rest_api/rest_api/settings.py +130 -0
- holado_django/server/django_projects/rest_api/rest_api/urls.py +35 -0
- holado_django/server/django_projects/rest_api/rest_api/wsgi.py +16 -0
- holado_django/server/django_server.py +110 -0
- holado_django/server/grpc_django_server.py +57 -0
- holado_django/tests/behave/steps/__init__.py +16 -0
- holado_django/tests/behave/steps/django_server_steps.py +83 -0
- holado_grpc/tests/behave/steps/private/api/grpc_steps.py +9 -9
- holado_multitask/multitasking/multitask_manager.py +36 -10
- holado_python/standard_library/ssl/resources/certificates/tcpbin.crt +16 -16
- holado_python/standard_library/ssl/resources/certificates/tcpbin.key +26 -26
- holado_rest/api/rest/TODO.txt +1 -1
- holado_rest/tests/behave/steps/private/api/rest_steps.py +11 -13
- holado_system/system/command/command.py +31 -9
- holado_system/system/global_system.py +3 -3
- test_holado/environment.py +6 -4
- test_holado/features/NonReg/api/REST.feature +7 -2
- test_holado/features/NonReg/api/gRPC.feature +0 -6
- test_holado/initialize_holado.py +62 -0
- test_holado/logging.conf +3 -0
- test_holado/tools/django/api_rest/db.sqlite3 +0 -0
- {holado-0.4.1.dist-info → holado-0.4.2.dist-info}/WHEEL +0 -0
- {holado-0.4.1.dist-info → holado-0.4.2.dist-info}/licenses/LICENSE +0 -0
- /holado_helper/holado_module_template/{test → tests}/behave/steps/__init__.py +0 -0
- /holado_helper/holado_module_template/{test → tests}/behave/steps/private/__init__.py +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
15
|
+
import logging
|
|
16
|
+
from holado_core.common.tools.tools import Tools
|
|
17
|
+
import os
|
|
18
|
+
from holado_core.tools.abstracts.blocking_command_service import BlockingCommandService
|
|
19
|
+
from holado_system.system.command.command import CommandStates
|
|
20
|
+
from holado_core.common.handlers.wait import WaitFuncResultVerifying
|
|
21
|
+
from holado.common.handlers.object import DeleteableObject
|
|
22
|
+
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
import django # @UnusedImport
|
|
27
|
+
with_django = True
|
|
28
|
+
except Exception as exc:
|
|
29
|
+
if Tools.do_log(logger, logging.DEBUG):
|
|
30
|
+
logger.debug(f"DjangoServer is not available. Initialization failed on error: {exc}")
|
|
31
|
+
with_django = False
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DjangoServer(DeleteableObject):
|
|
35
|
+
"""
|
|
36
|
+
Django server
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def is_available(cls):
|
|
41
|
+
return with_django
|
|
42
|
+
|
|
43
|
+
def __init__(self, name, django_project_path, port=8000, runserver_args=None):
|
|
44
|
+
super().__init__(name)
|
|
45
|
+
|
|
46
|
+
self.__django_project_path = django_project_path
|
|
47
|
+
self.__runserver_port = port
|
|
48
|
+
self.__runserver_args = runserver_args
|
|
49
|
+
self.__project_command = None
|
|
50
|
+
|
|
51
|
+
if not os.path.exists(django_project_path):
|
|
52
|
+
raise TechnicalException(f"Django project doesn't exist (project path: '{django_project_path}')")
|
|
53
|
+
|
|
54
|
+
def _delete_object(self):
|
|
55
|
+
if self.__project_command is not None and self.__project_command.status == CommandStates.Running:
|
|
56
|
+
self.stop()
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def django_project_path(self):
|
|
60
|
+
return self.__django_project_path
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def runserver_port(self):
|
|
64
|
+
return self.__runserver_port
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def runserver_args(self):
|
|
68
|
+
return self.__runserver_args
|
|
69
|
+
|
|
70
|
+
def start(self):
|
|
71
|
+
self.__start_server_by_command()
|
|
72
|
+
|
|
73
|
+
def __start_server_by_command(self):
|
|
74
|
+
self.__project_command = self._new_project_command()
|
|
75
|
+
self.__project_command.start()
|
|
76
|
+
self._wait_until_server_is_reachable()
|
|
77
|
+
|
|
78
|
+
def _new_project_command(self):
|
|
79
|
+
manage_path = os.path.join(self.django_project_path, "manage.py")
|
|
80
|
+
cmd = f"python {manage_path} runserver {self.runserver_port}"
|
|
81
|
+
if self.runserver_args:
|
|
82
|
+
cmd += f" {self.runserver_args}"
|
|
83
|
+
|
|
84
|
+
res = BlockingCommandService(f"Command running Django server '{self.name}'", cmd)
|
|
85
|
+
res.auto_stop = True
|
|
86
|
+
|
|
87
|
+
return res
|
|
88
|
+
|
|
89
|
+
def _wait_until_server_is_reachable(self):
|
|
90
|
+
import requests
|
|
91
|
+
url = f"http://127.0.0.1:{self.runserver_port}"
|
|
92
|
+
redo = WaitFuncResultVerifying("server is reachable",
|
|
93
|
+
lambda: requests.get(url),
|
|
94
|
+
lambda result: result and result.status_code == 200 )
|
|
95
|
+
redo.ignoring(Exception)
|
|
96
|
+
redo.polling_every(0.01)
|
|
97
|
+
redo.execute()
|
|
98
|
+
|
|
99
|
+
def stop(self):
|
|
100
|
+
if self.__project_command is None or self.__project_command.status != CommandStates.Running:
|
|
101
|
+
raise TechnicalException(f"Django server of project '{self.name}' is not running (status: {self.__project_command.status if self.__project_command else 'Unkown'})")
|
|
102
|
+
self.__project_command.stop()
|
|
103
|
+
|
|
104
|
+
def join(self, timeout=None):
|
|
105
|
+
self.__project_command.join(timeout)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
|
|
2
|
+
#################################################
|
|
3
|
+
# HolAdo (Holistic Automation do)
|
|
4
|
+
#
|
|
5
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
+
#
|
|
9
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
+
|
|
11
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
12
|
+
#################################################
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
import os
|
|
16
|
+
from holado_core.tools.abstracts.blocking_command_service import BlockingCommandService
|
|
17
|
+
from holado_django.server.django_server import DjangoServer
|
|
18
|
+
from holado_core.common.handlers.wait import WaitFuncResultVerifying
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GrpcDjangoServer(DjangoServer):
|
|
24
|
+
"""
|
|
25
|
+
gRPC Django server
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, name, django_project_path, runserver_args=None):
|
|
29
|
+
super().__init__(name, django_project_path, port=50051, runserver_args=runserver_args)
|
|
30
|
+
|
|
31
|
+
def _new_project_command(self):
|
|
32
|
+
manage_path = os.path.join(self.django_project_path, "manage.py")
|
|
33
|
+
cmd = f"python {manage_path} grpcrunserver"
|
|
34
|
+
if self.runserver_args:
|
|
35
|
+
cmd += f" {self.runserver_args}"
|
|
36
|
+
|
|
37
|
+
res = BlockingCommandService(f"Command running gRPC Django server '{self.name}'", cmd)
|
|
38
|
+
res.auto_stop = True
|
|
39
|
+
|
|
40
|
+
return res
|
|
41
|
+
|
|
42
|
+
def _wait_until_server_is_reachable(self):
|
|
43
|
+
import grpc_requests
|
|
44
|
+
|
|
45
|
+
endpoint = f"localhost:{self.runserver_port}"
|
|
46
|
+
def request_is_unimplemented():
|
|
47
|
+
try:
|
|
48
|
+
grpc_requests.Client.get_by_endpoint(endpoint)
|
|
49
|
+
except Exception as exc:
|
|
50
|
+
if "status = StatusCode.UNIMPLEMENTED" in str(exc):
|
|
51
|
+
return True
|
|
52
|
+
return False
|
|
53
|
+
redo = WaitFuncResultVerifying("server is reachable", request_is_unimplemented, lambda result: result )
|
|
54
|
+
redo.polling_every(0.01)
|
|
55
|
+
redo.execute()
|
|
56
|
+
|
|
57
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
#################################################
|
|
4
|
+
# HolAdo (Holistic Automation do)
|
|
5
|
+
#
|
|
6
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
7
|
+
#
|
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
11
|
+
|
|
12
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
13
|
+
#################################################
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from .django_server_steps import *
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
#################################################
|
|
4
|
+
# HolAdo (Holistic Automation do)
|
|
5
|
+
#
|
|
6
|
+
# (C) Copyright 2021-2025 by Eric Klumpp
|
|
7
|
+
#
|
|
8
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
9
|
+
#
|
|
10
|
+
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
11
|
+
|
|
12
|
+
# The Software is provided “as is”, without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages or other liability, whether in an action of contract, tort or otherwise, arising from, out of or in connection with the software or the use or other dealings in the Software.
|
|
13
|
+
#################################################
|
|
14
|
+
|
|
15
|
+
from holado.common.context.session_context import SessionContext
|
|
16
|
+
from holado_test.behave.behave import * # @UnusedWildImport
|
|
17
|
+
import logging
|
|
18
|
+
from holado_test.scenario.step_tools import StepTools
|
|
19
|
+
from holado_django.server.django_server import DjangoServer
|
|
20
|
+
from holado_test.behave.scenario.behave_step_tools import BehaveStepTools
|
|
21
|
+
from holado_value.common.tables.converters.value_table_converter import ValueTableConverter
|
|
22
|
+
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
23
|
+
from holado_django.server.grpc_django_server import GrpcDjangoServer
|
|
24
|
+
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def __get_session_context():
|
|
29
|
+
return SessionContext.instance()
|
|
30
|
+
|
|
31
|
+
def __get_scenario_context():
|
|
32
|
+
return __get_session_context().get_scenario_context()
|
|
33
|
+
|
|
34
|
+
def __get_text_interpreter():
|
|
35
|
+
return __get_scenario_context().get_text_interpreter()
|
|
36
|
+
|
|
37
|
+
def __get_variable_manager():
|
|
38
|
+
return __get_scenario_context().get_variable_manager()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@Given(r"(?P<var_name>{Variable}) = new Django server")
|
|
43
|
+
def step_impl(context, var_name):
|
|
44
|
+
var_name = StepTools.evaluate_variable_name(var_name)
|
|
45
|
+
table = BehaveStepTools.get_step_table(context)
|
|
46
|
+
|
|
47
|
+
kwargs = ValueTableConverter.convert_name_value_table_2_json_object(table)
|
|
48
|
+
if 'django_project_path' not in kwargs:
|
|
49
|
+
raise TechnicalException("Parameter 'django_project_path' is required")
|
|
50
|
+
if 'name' not in kwargs:
|
|
51
|
+
kwargs['name'] = f"Django server ({kwargs['django_project_path']})"
|
|
52
|
+
|
|
53
|
+
server = DjangoServer(**kwargs)
|
|
54
|
+
|
|
55
|
+
__get_variable_manager().register_variable(var_name, server)
|
|
56
|
+
|
|
57
|
+
@Given(r"(?P<var_name>{Variable}) = new gRPC Django server")
|
|
58
|
+
def step_impl(context, var_name):
|
|
59
|
+
var_name = StepTools.evaluate_variable_name(var_name)
|
|
60
|
+
table = BehaveStepTools.get_step_table(context)
|
|
61
|
+
|
|
62
|
+
kwargs = ValueTableConverter.convert_name_value_table_2_json_object(table)
|
|
63
|
+
if 'django_project_path' not in kwargs:
|
|
64
|
+
raise TechnicalException("Parameter 'django_project_path' is required")
|
|
65
|
+
if 'name' not in kwargs:
|
|
66
|
+
kwargs['name'] = f"Django server ({kwargs['django_project_path']})"
|
|
67
|
+
|
|
68
|
+
server = GrpcDjangoServer(**kwargs)
|
|
69
|
+
|
|
70
|
+
__get_variable_manager().register_variable(var_name, server)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@Step(r"start \(Django server: (?P<var_server>{Variable})\)")
|
|
74
|
+
def step_impl(context, var_server):
|
|
75
|
+
server = StepTools.evaluate_variable_value(var_server)
|
|
76
|
+
server.start()
|
|
77
|
+
|
|
78
|
+
@Step(r"stop \(Django server: (?P<var_server>{Variable})\)")
|
|
79
|
+
def step_impl(context, var_server):
|
|
80
|
+
server = StepTools.evaluate_variable_value(var_server)
|
|
81
|
+
server.stop()
|
|
82
|
+
|
|
83
|
+
|
|
@@ -49,18 +49,18 @@ def step_impl(context, var_name):
|
|
|
49
49
|
var_name = StepTools.evaluate_variable_name(var_name)
|
|
50
50
|
|
|
51
51
|
here = os.path.abspath(os.path.dirname(__file__))
|
|
52
|
-
|
|
53
|
-
manage_path = os.path.join(api_grpc_path, "manage.py")
|
|
54
|
-
cmd = f"python {manage_path} grpcrunserver"
|
|
52
|
+
django_project_path = os.path.normpath(os.path.join(here, "..", "..", "..", "..", "..", "..", "..", "tests", "behave", "test_holado", "tools", "django", "api_grpc"))
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
execute_steps(u"""
|
|
55
|
+
Given {var_name} = new gRPC Django server
|
|
56
|
+
| Name | Value |
|
|
57
|
+
| 'name' | 'gRPC server for holado tests' |
|
|
58
|
+
| 'django_project_path' | '{django_project_path}' |
|
|
59
|
+
When start (Django server: {var_name})
|
|
60
|
+
""".format(var_name=var_name, django_project_path=django_project_path))
|
|
61
61
|
|
|
62
62
|
# Update imported grpc messages and services
|
|
63
|
-
proto_path = os.path.join(
|
|
63
|
+
proto_path = os.path.join(django_project_path, "api_grpc", "api1", "proto")
|
|
64
64
|
__get_session_context().protobuf_messages.import_all_compiled_proto(proto_path)
|
|
65
65
|
__get_session_context().grpc_services.import_all_compiled_proto(proto_path)
|
|
66
66
|
|
|
@@ -22,6 +22,8 @@ from holado_core.common.tools.tools import Tools
|
|
|
22
22
|
from holado_python.standard_library.typing import Typing
|
|
23
23
|
from holado.common.handlers.undefined import default_context
|
|
24
24
|
from holado.common.context.session_context import SessionContext
|
|
25
|
+
import psutil
|
|
26
|
+
import signal
|
|
25
27
|
|
|
26
28
|
logger = logging.getLogger(__name__)
|
|
27
29
|
|
|
@@ -60,16 +62,40 @@ class MultitaskManager(object):
|
|
|
60
62
|
if pid is None:
|
|
61
63
|
return os.getppid()
|
|
62
64
|
else:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
process = psutil.Process(pid)
|
|
66
|
+
return process.ppid()
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def get_children_process_ids(cls, pid=None, recursive=False):
|
|
70
|
+
if pid is None:
|
|
71
|
+
pid = os.getpid()
|
|
72
|
+
|
|
73
|
+
process = psutil.Process(pid)
|
|
74
|
+
children = process.children(recursive=recursive)
|
|
75
|
+
return [c.pid for c in children]
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def kill_process(cls, pid, sig=signal.SIGTERM, do_kill_children=True, recursively=True):
|
|
79
|
+
try:
|
|
80
|
+
process = psutil.Process(pid)
|
|
81
|
+
except psutil.NoSuchProcess:
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Kill children
|
|
85
|
+
if do_kill_children:
|
|
86
|
+
children = process.children(recursive=recursively)
|
|
87
|
+
for proc in children:
|
|
88
|
+
try:
|
|
89
|
+
proc.send_signal(sig)
|
|
90
|
+
except signal.SIGTERM:
|
|
91
|
+
pass
|
|
92
|
+
|
|
93
|
+
# Kill process
|
|
94
|
+
try:
|
|
95
|
+
process.send_signal(sig)
|
|
96
|
+
except signal.SIGTERM:
|
|
97
|
+
pass
|
|
98
|
+
|
|
73
99
|
@classmethod
|
|
74
100
|
def has_thread_native_id(cls):
|
|
75
101
|
from holado_multitask.multithreading.threadsmanager import ThreadsManager
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
MIIDZTCCAk2gAwIBAgIBKjANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMCVVMx
|
|
3
3
|
CzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMQ8wDQYDVQQKDAZ0
|
|
4
4
|
Y3BiaW4xDDAKBgNVBAsMA29wczETMBEGA1UEAwwKdGNwYmluLmNvbTEjMCEGCSqG
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
FOLuMowBSAZfV5v82LmlaIIOvU/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
SIb3DQEJARYUaGFycnliYWdkaUBnbWFpbC5jb20wHhcNMjUwNzAxMTQyMDI3WhcN
|
|
6
|
+
MjUwNzAyMTQyMDI3WjAcMRowGAYDVQQDDBF0Y3BiaW4uY29tLWNsaWVudDCCASIw
|
|
7
|
+
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALmLkz54fCoSSM/uG945GvhavQF8
|
|
8
|
+
unsEDd0RuHWZPIBcrlEzhLLiiiegET4UFlywF4wSfbiNGgwr3Uw+6ph3xLrNs91B
|
|
9
|
+
EYqOGesT9wRPMlon88qsaVIFfbqfg4e1m0si+/NwZMk+5bBeYC0blXk7HiTZ5KJt
|
|
10
|
+
QNLeduIYaPSuyq+qxl/xDqWOifbKcgycitgCPKPxohtwa5h6IjU3WYb7+xNPt3cx
|
|
11
|
+
+hoCwfab1NgVBse6ZsUf81nkCEVKKLaNvlDkmXp9ItqZZay+0/yzLCgNyf8gDprU
|
|
12
|
+
8u+nDM+pcz83OtIQWVeN5MtFjkA4nik55yqdlqnB1OWzEzaMSMh6Vsy13xMCAwEA
|
|
13
|
+
AaNCMEAwHQYDVR0OBBYEFG5H5JaQhWehs8VRJu88HbHgK9CvMB8GA1UdIwQYMBaA
|
|
14
|
+
FOLuMowBSAZfV5v82LmlaIIOvU/DMA0GCSqGSIb3DQEBCwUAA4IBAQCs93UG22r0
|
|
15
|
+
ZIF10IAoXVbPWOeXpKJgWpsQYURsGw7sB+Cgr/vK3P1lkZVMl72LUzNazmOQldev
|
|
16
|
+
zUQ0TtOq24go1iAYWc7zYlxo9OHNkbAUDoViKP63K/CkXNCIkXg00vmEUco1PQWU
|
|
17
|
+
+OEaTNrQCeiW2eqYie9WNc4T5a7aUHT3Xno7G8KXTM7gtW35FNI/b0CwVWHRFzev
|
|
18
|
+
n9VhRI9xrNYxpDqqxYu7diIV4TQVmscmNicuEtDB98kJ7yOAhlpzQhIFi1vQEefD
|
|
19
|
+
4gZZ3ihlLd2XJWxiXZgeiz7dzva4oGcr9mU5Uohza3u/sjF34kx02+gNuv8x4Wil
|
|
20
|
+
CU9Rl0WFGJ00
|
|
21
21
|
-----END CERTIFICATE-----
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
-----BEGIN PRIVATE KEY-----
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/
|
|
18
|
-
|
|
19
|
-
/
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
2
|
+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5i5M+eHwqEkjP
|
|
3
|
+
7hveORr4Wr0BfLp7BA3dEbh1mTyAXK5RM4Sy4oonoBE+FBZcsBeMEn24jRoMK91M
|
|
4
|
+
PuqYd8S6zbPdQRGKjhnrE/cETzJaJ/PKrGlSBX26n4OHtZtLIvvzcGTJPuWwXmAt
|
|
5
|
+
G5V5Ox4k2eSibUDS3nbiGGj0rsqvqsZf8Q6ljon2ynIMnIrYAjyj8aIbcGuYeiI1
|
|
6
|
+
N1mG+/sTT7d3MfoaAsH2m9TYFQbHumbFH/NZ5AhFSii2jb5Q5Jl6fSLamWWsvtP8
|
|
7
|
+
sywoDcn/IA6a1PLvpwzPqXM/NzrSEFlXjeTLRY5AOJ4pOecqnZapwdTlsxM2jEjI
|
|
8
|
+
elbMtd8TAgMBAAECggEAfLWcfSOcSObLO76NyppVT1IlsWc1K9O4wbrUYW5iZOBm
|
|
9
|
+
Zbub2GQ9eY6zqCb2NMxCt2oCSFXGiSG+dy3eniX5+5ig6PiAIsGKGB/uKl5UuJYb
|
|
10
|
+
3UBu9astK49lZ4Sf4Sudbq0/gKge16FHQWpF2BrtEtXFP4rxRAo0m5jOio8lOlYG
|
|
11
|
+
VSBFrkww7aS0pbymELj+Yg0twrUQjeG/hhoA4juiAq8T6oilrNfxhgc8pi2e23Ix
|
|
12
|
+
iokPjVWWAylKr6+oKhgBj/MKoIcEPeyYem1rBCesO2Th5CHy4YwIsZq+456Wo9/z
|
|
13
|
+
efxjnr+1vrsH+WK83nff3wUMruchKbdP1p9sMSkwqQKBgQD0y8b7sK4omV/JRdS3
|
|
14
|
+
sADYETu2wshP22EuUbkDPICe5/ct1LWlTJAI84MkMcg4rOHuLubD32ttRA3SWnK/
|
|
15
|
+
eqXB3gkcstVhipjj5qH5sg3gCIOa5rmePY1Zn5v75BImYzHYBfqQ0Z99czBNQ4un
|
|
16
|
+
MPMxe1IRT+b6aU7EOWjSWG2X/wKBgQDCCZGpv+pFQqxb5YjPQqDn/7M9wE89b22T
|
|
17
|
+
G2weESzoBrnLCUA4M0QEhhgBkcb9grZQ0aCOzjqKTDF/2AnFOhP6IIzEVxkrsC/0
|
|
18
|
+
c150lU8kiIlkymVF7N5vwayPFUeNqaO5NdHOYu0HkEQ8h9FCFurc0OjA/8xRPXkp
|
|
19
|
+
AGar8P/Y7QKBgE+5jjSqdg4C5Y9Hjt/EEoJMGoaLKXHYoO3U78x+B+W45memvwH2
|
|
20
|
+
zXIc3LkM/Yh3xZ0s6TshqHsNjvLTQkvaReG9znnqRFRgLysKEfagZqRwIWxxeEJx
|
|
21
|
+
CXgG42ZGASM/axxP1isUGj1hJnoDZZgt+QZEg5Xfz/n+EgkWKW1YH1lBAoGAMw7L
|
|
22
|
+
ioxae+Egc4oBpvAUYRfStXQOJc9VWPlFSOAiHefvKbMEeAVdZ4dVd8xBPWIQ0VFn
|
|
23
|
+
20v+8Xc9KzPQ1loC+bVo9R0qHWneJIfbGfhT+/wFk0UCwxSiL2waGQhzbJ5v24OC
|
|
24
|
+
8rjrQCtBGWBvuuFG6dX6+RYWUGZJpHVbjvD6kb0CgYAnU00V1AZu39ku1iozaHoY
|
|
25
|
+
STedxCDtGZotOISDFzaqIxaJ1JUeWZ/90ZMIVHdE+pP8n2P8MN7rppBbTN6Mxcbq
|
|
26
|
+
uE9BfZJGN5A8PuugoJWBJwkfnhrEMXXSpz5SPQntCkrET7pkAW2Nx1CWRQKaj1pu
|
|
27
|
+
+CKEVUIhv/elJOdMV9mGbA==
|
|
28
28
|
-----END PRIVATE KEY-----
|
holado_rest/api/rest/TODO.txt
CHANGED
|
@@ -17,6 +17,7 @@ from holado_test.behave.behave import * # @UnusedWildImport
|
|
|
17
17
|
import os.path
|
|
18
18
|
import logging
|
|
19
19
|
from holado_test.scenario.step_tools import StepTools
|
|
20
|
+
from holado_django.server.django_server import DjangoServer
|
|
20
21
|
|
|
21
22
|
logger = logging.getLogger(__name__)
|
|
22
23
|
|
|
@@ -40,22 +41,19 @@ def step_impl(context, var_name):
|
|
|
40
41
|
var_name = StepTools.evaluate_variable_name(var_name)
|
|
41
42
|
|
|
42
43
|
here = os.path.abspath(os.path.dirname(__file__))
|
|
43
|
-
|
|
44
|
-
cmd = f"python {manage_path} runserver"
|
|
44
|
+
django_project_path = os.path.normpath(os.path.join(here, "..", "..", "..", "..", "..", "..", "..", "tests", "behave", "test_holado", "tools", "django", "api_rest"))
|
|
45
45
|
|
|
46
46
|
execute_steps(u"""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
When wait 5 seconds
|
|
55
|
-
Then command {var_name} has status Running
|
|
56
|
-
""".format(cmd=cmd, var_name=var_name))
|
|
57
|
-
|
|
47
|
+
Given {var_name} = new Django server
|
|
48
|
+
| Name | Value |
|
|
49
|
+
| 'name' | 'REST server for holado tests' |
|
|
50
|
+
| 'django_project_path' | '{django_project_path}' |
|
|
51
|
+
| 'port' | 8000 |
|
|
52
|
+
When start (Django server: {var_name})
|
|
53
|
+
""".format(var_name=var_name, django_project_path=django_project_path))
|
|
58
54
|
|
|
55
|
+
|
|
56
|
+
|
|
59
57
|
@Given(r"(?P<var_name>{Variable}) = new internal REST client")
|
|
60
58
|
def step_impl(context, var_name):
|
|
61
59
|
var_name = StepTools.evaluate_variable_name(var_name)
|
|
@@ -20,6 +20,9 @@ import time
|
|
|
20
20
|
from enum import IntEnum
|
|
21
21
|
from holado_core.common.exceptions.functional_exception import FunctionalException
|
|
22
22
|
import copy
|
|
23
|
+
import signal
|
|
24
|
+
from holado_core.common.tools.tools import Tools
|
|
25
|
+
from holado_multitask.multitasking.multitask_manager import MultitaskManager
|
|
23
26
|
|
|
24
27
|
logger = logging.getLogger(__name__)
|
|
25
28
|
|
|
@@ -31,6 +34,7 @@ class CommandStates(IntEnum):
|
|
|
31
34
|
Success = 3
|
|
32
35
|
Error = 4
|
|
33
36
|
|
|
37
|
+
|
|
34
38
|
class Command(threading.Thread):
|
|
35
39
|
"""
|
|
36
40
|
Execute a command in a thread.
|
|
@@ -58,6 +62,7 @@ class Command(threading.Thread):
|
|
|
58
62
|
self.__callback_delay_ms = None
|
|
59
63
|
self.__external_parameters = {}
|
|
60
64
|
self.__subprocess_kwargs = subprocess_kwargs
|
|
65
|
+
self.__stop_signal = signal.SIGTERM
|
|
61
66
|
|
|
62
67
|
|
|
63
68
|
@property
|
|
@@ -94,29 +99,38 @@ class Command(threading.Thread):
|
|
|
94
99
|
return self.__process.returncode
|
|
95
100
|
else:
|
|
96
101
|
return None
|
|
97
|
-
|
|
102
|
+
|
|
98
103
|
@property
|
|
99
104
|
def callback(self):
|
|
100
105
|
return self.__callback
|
|
101
|
-
|
|
106
|
+
|
|
102
107
|
@callback.setter
|
|
103
108
|
def callback(self, callback):
|
|
104
109
|
"""Set callback called when execution end."""
|
|
105
110
|
self.__callback = callback
|
|
106
|
-
|
|
111
|
+
|
|
107
112
|
@property
|
|
108
113
|
def callback_delay_ms(self):
|
|
109
114
|
return self.__callback_delay_ms
|
|
110
|
-
|
|
115
|
+
|
|
111
116
|
@callback_delay_ms.setter
|
|
112
117
|
def callback_delay_ms(self, delay_ms):
|
|
113
118
|
"""Set callback delay in ms."""
|
|
114
119
|
self.__callback_delay_ms = delay_ms
|
|
115
|
-
|
|
120
|
+
|
|
116
121
|
@property
|
|
117
122
|
def external_parameters(self):
|
|
118
123
|
return self.__external_parameters
|
|
119
|
-
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def stop_signal(self):
|
|
127
|
+
return self.__stop_signal
|
|
128
|
+
|
|
129
|
+
@stop_signal.setter
|
|
130
|
+
def stop_signal(self, stop_signal):
|
|
131
|
+
"""Set stop signal."""
|
|
132
|
+
self.__stop_signal = stop_signal
|
|
133
|
+
|
|
120
134
|
def run(self):
|
|
121
135
|
logger.debug("Call command: {}".format(self.cmd))
|
|
122
136
|
try:
|
|
@@ -139,7 +153,7 @@ class Command(threading.Thread):
|
|
|
139
153
|
|
|
140
154
|
self.__stdout = ""
|
|
141
155
|
self.__stderr = ""
|
|
142
|
-
while
|
|
156
|
+
while self.__process.returncode is None:
|
|
143
157
|
# Wait a small time and in same time yield this thread
|
|
144
158
|
time.sleep(0.001)
|
|
145
159
|
|
|
@@ -175,7 +189,7 @@ class Command(threading.Thread):
|
|
|
175
189
|
logger.debug(f"Command [{self.cmd}] has finished, calling callback...")
|
|
176
190
|
self.callback(self)
|
|
177
191
|
elif self.error is not None:
|
|
178
|
-
logger.error(f"Command [{self.cmd}] has finished on error
|
|
192
|
+
logger.error(f"Command [{self.cmd}] has finished on error: {self.error}")
|
|
179
193
|
elif self.state == CommandStates.Error:
|
|
180
194
|
logger.error(f"Command [{self.cmd}] has finished on error code {self.return_code} and stderr: {self.stderr}")
|
|
181
195
|
elif self.state != CommandStates.Success:
|
|
@@ -208,13 +222,21 @@ class Command(threading.Thread):
|
|
|
208
222
|
raise FunctionalException(msg)
|
|
209
223
|
|
|
210
224
|
def kill(self):
|
|
225
|
+
# Note: kill is equivalent to terminate in subprocess implementation
|
|
211
226
|
if self.state == CommandStates.Running:
|
|
212
227
|
self.__process.kill()
|
|
213
228
|
|
|
214
229
|
def terminate(self):
|
|
215
230
|
if self.state == CommandStates.Running:
|
|
216
231
|
self.__process.terminate()
|
|
217
|
-
|
|
232
|
+
|
|
233
|
+
def stop(self):
|
|
234
|
+
if self.state == CommandStates.Running:
|
|
235
|
+
if Tools.do_log(logger, logging.DEBUG):
|
|
236
|
+
logger.debug(f"Stopping command [{self.cmd}] with signal {self.__stop_signal} and PID {self.__process.pid}")
|
|
237
|
+
|
|
238
|
+
MultitaskManager.kill_process(self.__process.pid, sig=self.__stop_signal, do_kill_children=True, recursively=True)
|
|
239
|
+
|
|
218
240
|
def __repr__(self):
|
|
219
241
|
return pprint.pformat({'cmd' : self.cmd,
|
|
220
242
|
'is alive' : self.is_alive() })
|
|
@@ -14,9 +14,7 @@
|
|
|
14
14
|
import logging
|
|
15
15
|
from holado.common.handlers.enums import AutoNumber
|
|
16
16
|
import platform
|
|
17
|
-
from holado_system.system.command.command import Command, CommandStates
|
|
18
17
|
from holado_core.common.exceptions.technical_exception import TechnicalException
|
|
19
|
-
from holado_system.system.command.command_result import CommandResult
|
|
20
18
|
import time
|
|
21
19
|
import os
|
|
22
20
|
from holado_core.common.tools.tools import Tools
|
|
@@ -87,6 +85,9 @@ class GlobalSystem(object):
|
|
|
87
85
|
|
|
88
86
|
@classmethod
|
|
89
87
|
def execute_command(cls, cmd, do_log_output=False, do_raise_on_stderr=False):
|
|
88
|
+
from holado_system.system.command.command import Command, CommandStates
|
|
89
|
+
from holado_system.system.command.command_result import CommandResult
|
|
90
|
+
|
|
90
91
|
command = Command(cmd, do_log_output=do_log_output, do_raise_on_stderr=do_raise_on_stderr)
|
|
91
92
|
command.start()
|
|
92
93
|
command.join()
|
|
@@ -183,5 +184,4 @@ class GlobalSystem(object):
|
|
|
183
184
|
return port
|
|
184
185
|
return None
|
|
185
186
|
|
|
186
|
-
|
|
187
187
|
|
test_holado/environment.py
CHANGED
|
@@ -19,10 +19,12 @@ import logging
|
|
|
19
19
|
|
|
20
20
|
# Add testing solution sources paths
|
|
21
21
|
here = os.path.abspath(os.path.dirname(__file__))
|
|
22
|
-
sys.path.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
sys.path.insert(0, here)
|
|
23
|
+
|
|
24
|
+
# Add HolAdo source paths (needed when using a clone of HolAdo project)
|
|
25
|
+
from initialize_holado import insert_holado_source_paths
|
|
26
|
+
insert_holado_source_paths()
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
# Configure HolAdo
|
|
28
30
|
import holado
|