33import os
44import shutil
55import subprocess
6- from typing import Any , Dict , Optional , Set , Type , Union
6+ from typing import Any , Dict , List , Optional , Set , Type , Union
77
88from irctest .basecontrollers import (
99 BaseServerController ,
@@ -139,6 +139,7 @@ class ErgoController(BaseServerController, DirectoryBasedController):
139139 supported_sasl_mechanisms = {"PLAIN" , "SCRAM-SHA-256" }
140140 supports_sts = True
141141 extban_mute_char = "m"
142+ mysql_proc : Optional [subprocess .Popen ] = None
142143
143144 def create_config (self ) -> None :
144145 super ().create_config ()
@@ -215,6 +216,16 @@ def run(
215216 [* faketime_cmd , "ergo" , "run" , "--conf" , self ._config_path , "--quiet" ]
216217 )
217218
219+ def terminate (self ) -> None :
220+ if self .mysql_proc is not None :
221+ self .mysql_proc .terminate ()
222+ super ().terminate ()
223+
224+ def kill (self ) -> None :
225+ if self .mysql_proc is not None :
226+ self .mysql_proc .kill ()
227+ super ().kill ()
228+
218229 def wait_for_services (self ) -> None :
219230 # Nothing to wait for, they start at the same time as Ergo.
220231 pass
@@ -266,18 +277,12 @@ def addLoggingToConfig(self, config: Optional[Dict] = None) -> Dict:
266277 config .update (LOGGING_CONFIG )
267278 return config
268279
269- def addMysqlToConfig (self , config : Optional [Dict ] = None ) -> Dict :
270- mysql_password = os .getenv ("MYSQL_PASSWORD" )
271- if config is None :
272- config = self .baseConfig ()
273- if not mysql_password :
274- return config
275-
280+ def addMysqlToConfig (self , config : Dict ) -> Dict :
281+ socket_path = self .startMysql ()
282+ self .createMysqlDatabase (socket_path , "ergo_history" )
276283 config ["datastore" ]["mysql" ] = {
277284 "enabled" : True ,
278- "host" : "localhost" ,
279- "user" : "ergo" ,
280- "password" : mysql_password ,
285+ "socket-path" : socket_path ,
281286 "history-database" : "ergo_history" ,
282287 "timeout" : "3s" ,
283288 }
@@ -290,6 +295,56 @@ def addMysqlToConfig(self, config: Optional[Dict] = None) -> Dict:
290295 }
291296 return config
292297
298+ def startMysql (self ) -> str :
299+ """Starts a new MySQL server listening on a UNIX socket, returns the socket
300+ path"""
301+ assert self .directory
302+ mysql_dir = os .path .join (self .directory , "mysql" )
303+ socket_path = os .path .join (mysql_dir , "mysql.socket" )
304+ os .mkdir (mysql_dir )
305+
306+ print ("Starting MySQL..." )
307+ self .mysql_proc = subprocess .Popen (
308+ [
309+ "mysqld" ,
310+ "--no-defaults" ,
311+ "--tmpdir=" + mysql_dir ,
312+ "--datadir=" + mysql_dir ,
313+ "--socket=" + socket_path ,
314+ "--skip-networking" ,
315+ "--skip-grant-tables" ,
316+ ],
317+ stdout = subprocess .PIPE ,
318+ stderr = subprocess .STDOUT ,
319+ )
320+
321+ mysql_stdout = self .mysql_proc .stdout
322+ assert mysql_stdout is not None # for mypy...
323+ lines : List [bytes ] = []
324+ while self .mysql_proc .returncode is None :
325+ line = mysql_stdout .readline ()
326+ lines .append (lines )
327+ if b"mysqld: ready for connections." in line :
328+ break
329+ assert self .mysql_proc .returncode is None , (
330+ "MySQL unexpected stopped: " + b"\n " .join (lines ).decode ()
331+ )
332+ print ("MySQL started" )
333+
334+ return socket_path
335+
336+ def createMysqlDatabase (self , socket_path : str , database_name : str ) -> None :
337+ subprocess .check_call (
338+ [
339+ "mysql" ,
340+ "--no-defaults" ,
341+ "-S" ,
342+ socket_path ,
343+ "-e" ,
344+ f"CREATE DATABASE { database_name } ;" ,
345+ ]
346+ )
347+
293348 def rehash (self , case : BaseServerTestCase , config : Dict ) -> None :
294349 self ._config = config
295350 self ._write_config ()
0 commit comments