comparison NewTests/helpers.py @ 474:6917a26881ed

NewTests working with Docker
author Alain Mazy <am@osimis.io>
date Mon, 02 May 2022 17:05:42 +0200
parents 4ee85b016a40
children fe37cf5e9c02
comparison
equal deleted inserted replaced
473:4ee85b016a40 474:6917a26881ed
18 } 18 }
19 19
20 class Helpers: 20 class Helpers:
21 21
22 orthanc_under_tests_hostname: str = 'localhost' 22 orthanc_under_tests_hostname: str = 'localhost'
23 orthanc_under_tests_http_port: int = 8042 23 orthanc_under_tests_http_port: int = 8052
24 orthanc_under_tests_dicom_port: int = 4252
24 orthanc_under_tests_exe: str = None 25 orthanc_under_tests_exe: str = None
25 orthanc_previous_version_exe: str = None 26 orthanc_previous_version_exe: str = None
26 orthanc_under_tests_docker_image: str = None 27 orthanc_under_tests_docker_image: str = None
27 skip_preparation: bool = False 28 skip_preparation: bool = False
28 break_after_preparation: bool = False 29 break_after_preparation: bool = False
30 31
31 @classmethod 32 @classmethod
32 def get_orthanc_url(cls): 33 def get_orthanc_url(cls):
33 return f"http://{cls.orthanc_under_tests_hostname}:{cls.orthanc_under_tests_http_port}" 34 return f"http://{cls.orthanc_under_tests_hostname}:{cls.orthanc_under_tests_http_port}"
34 35
36 @classmethod
37 def is_docker(cls):
38 return cls.orthanc_under_tests_exe is None and cls.orthanc_under_tests_docker_image is not None
39
40 @classmethod
41 def is_exe(cls):
42 return cls.orthanc_under_tests_exe is not None and cls.orthanc_under_tests_docker_image is None
43
35 class OrthancTestCase(unittest.TestCase): 44 class OrthancTestCase(unittest.TestCase):
36 45
37 o: OrthancApiClient = None # the orthanc under tests api client 46 o: OrthancApiClient = None # the orthanc under tests api client
38 _orthanc_process = None 47 _orthanc_process = None
48 _orthanc_container_name = None
39 _orthanc_is_running = False 49 _orthanc_is_running = False
40 _orthanc_logger_thread = None 50 _orthanc_logger_thread = None
41 51
42 @classmethod 52 @classmethod
43 def setUpClass(cls): 53 def setUpClass(cls):
65 75
66 @classmethod 76 @classmethod
67 def generate_configuration(cls, config_name: str, config: object, storage_name: str, plugins = []): 77 def generate_configuration(cls, config_name: str, config: object, storage_name: str, plugins = []):
68 78
69 # add plugins and default storge directory 79 # add plugins and default storge directory
70 config["Plugins"] = plugins 80 if plugins and len(plugins) > 0:
71 81 config["Plugins"] = plugins
72 if not "StorageDirectory" in config: 82
83 if Helpers.is_exe() and not "StorageDirectory" in config:
73 config["StorageDirectory"] = cls.get_storage_path(storage_name=storage_name) 84 config["StorageDirectory"] = cls.get_storage_path(storage_name=storage_name)
74 85
75 if not "Name" in config: 86 if not "Name" in config:
76 config["Name"] = config_name 87 config["Name"] = config_name
77 88
78 if not "HttpPort" in config: 89 if not "HttpPort" in config:
79 config["HttpPort"] = Helpers.orthanc_under_tests_http_port 90 config["HttpPort"] = Helpers.orthanc_under_tests_http_port
91
92 if not "DicomPort" in config:
93 config["DicomPort"] = Helpers.orthanc_under_tests_dicom_port
80 94
81 # copy the values from the base config 95 # copy the values from the base config
82 for k, v in default_base_config.items(): 96 for k, v in default_base_config.items():
83 if not k in config: 97 if not k in config:
84 config[k] = v 98 config[k] = v
90 104
91 return path 105 return path
92 106
93 @classmethod 107 @classmethod
94 def clear_storage(cls, storage_name: str): 108 def clear_storage(cls, storage_name: str):
95 storage_path = cls.get_storage_path(storage_name=storage_name) 109 if Helpers.is_exe():
96 shutil.rmtree(storage_path) 110 storage_path = cls.get_storage_path(storage_name=storage_name)
97 111 shutil.rmtree(storage_path, ignore_errors=True)
98 112 elif Helpers.is_docker():
99 @classmethod 113 subprocess.run(["docker", "volume", "rm", storage_name])
100 def launch_orthanc_to_prepare_db(cls, config_name: str, config: object, storage_name: str, plugins = []): 114
101 # generate the configuration file 115 @classmethod
102 config_path = cls.generate_configuration( 116 def launch_orthanc_to_prepare_db(cls, config_name: str = None, config: object = None, config_path: str = None, storage_name: str = None, plugins = []):
103 config_name=config_name, 117 if config_name and storage_name and config:
104 storage_name=storage_name, 118 # generate the configuration file
105 config=config, 119 config_path = cls.generate_configuration(
106 plugins=plugins 120 config_name=config_name,
107 ) 121 storage_name=storage_name,
122 config=config,
123 plugins=plugins
124 )
125 elif not config_path or not storage_name or not config_name:
126 raise RuntimeError("Invalid configuration")
108 127
109 # run orthanc 128 # run orthanc
110 if Helpers.orthanc_previous_version_exe: 129 if Helpers.orthanc_previous_version_exe:
111 cls.launch_orthanc( 130 cls.launch_orthanc_exe(
112 exe_path=Helpers.orthanc_previous_version_exe, 131 exe_path=Helpers.orthanc_previous_version_exe,
113 config_path=config_path 132 config_path=config_path
114 ) 133 )
134 elif Helpers.orthanc_previous_version_docker_image:
135 cls.launch_orthanc_docker(
136 docker_image=Helpers.orthanc_previous_version_docker_image,
137 storage_name=storage_name,
138 config_name=config_name,
139 config_path=config_path
140 )
115 else: 141 else:
116 raise RuntimeError("No orthanc_previous_version_exe defined, can not launch Orthanc") 142 raise RuntimeError("Invalid configuration, can not launch Orthanc")
117 143
118 @classmethod 144 @classmethod
119 def launch_orthanc(cls, exe_path: str, config_path: str): 145 def launch_orthanc_under_tests(cls, config_name: str = None, config: object = None, config_path: str = None, storage_name: str = None, plugins = []):
146 if config_name and storage_name and config:
147 # generate the configuration file
148 config_path = cls.generate_configuration(
149 config_name=config_name,
150 storage_name=storage_name,
151 config=config,
152 plugins=plugins
153 )
154 elif not config_path or not storage_name or not config_name:
155 raise RuntimeError("Invalid configuration")
156
157 # run orthanc
158 if Helpers.orthanc_under_tests_exe:
159 cls.launch_orthanc_exe(
160 exe_path=Helpers.orthanc_under_tests_exe,
161 config_path=config_path
162 )
163 elif Helpers.orthanc_under_tests_docker_image:
164 cls.launch_orthanc_docker(
165 docker_image=Helpers.orthanc_under_tests_docker_image,
166 storage_name=storage_name,
167 config_name=config_name,
168 config_path=config_path
169 )
170 else:
171 raise RuntimeError("Invalid configuration, can not launch Orthanc")
172
173 @classmethod
174 def launch_orthanc_exe(cls, exe_path: str, config_path: str):
120 cls._orthanc_process = subprocess.Popen( 175 cls._orthanc_process = subprocess.Popen(
121 [exe_path, "--verbose", config_path], 176 [exe_path, "--verbose", config_path],
122 stdout=subprocess.PIPE, 177 stdout=subprocess.PIPE,
123 stderr=subprocess.PIPE 178 stderr=subprocess.PIPE
124 ) 179 )
129 print("Orthanc output\n" + output) 184 print("Orthanc output\n" + output)
130 185
131 raise RuntimeError(f"Orthanc failed to start '{exe_path}', conf = '{config_path}'. Check output above") 186 raise RuntimeError(f"Orthanc failed to start '{exe_path}', conf = '{config_path}'. Check output above")
132 187
133 @classmethod 188 @classmethod
189 def launch_orthanc_docker(cls, docker_image: str, storage_name: str, config_path: str, config_name: str):
190
191 cmd = [
192 "docker", "run", "--rm",
193 "-e", "VERBOSE_ENABLED=true",
194 "-e", "VERBOSE_STARTUP=true",
195 "-v", f"{config_path}:/etc/orthanc/orthanc.json",
196 "-v", f"{storage_name}:/var/lib/orthanc/db/",
197 "--name", config_name,
198 "-p", f"{Helpers.orthanc_under_tests_http_port}:{Helpers.orthanc_under_tests_http_port}",
199 "-p", f"{Helpers.orthanc_under_tests_dicom_port}:{Helpers.orthanc_under_tests_dicom_port}",
200 docker_image
201 ]
202 cls._orthanc_container_name = config_name
203 print("docker cmd line: " + " ".join(cmd))
204
205 cls._orthanc_process = subprocess.Popen(
206 cmd,
207 stdout=subprocess.PIPE,
208 stderr=subprocess.PIPE
209 )
210
211 cls.o.wait_started(10)
212 if not cls.o.is_alive():
213 output = cls.get_orthanc_process_output()
214 print("Orthanc output\n" + output)
215
216 raise RuntimeError(f"Orthanc failed to start Orthanc through Docker '{docker_image}', conf = '{config_path}'. Check output above")
217
218
219 @classmethod
134 def kill_orthanc(cls): 220 def kill_orthanc(cls):
135 cls._orthanc_process.kill() 221 if Helpers.is_exe():
222 cls._orthanc_process.kill()
223 else:
224 subprocess.run(["docker", "stop", cls._orthanc_container_name])
136 output = cls.get_orthanc_process_output() 225 output = cls.get_orthanc_process_output()
137 print("Orthanc output\n" + output) 226 print("Orthanc output\n" + output)
138 cls._orthanc_process = None 227 cls._orthanc_process = None
139 228
140 @classmethod 229 @classmethod