Use pathlib to work with temporary config dirs

This commit is contained in:
Valentin Lorentz 2022-09-10 11:38:29 +02:00 committed by Val Lorentz
parent dbdadec677
commit 507f5b7426
15 changed files with 51 additions and 67 deletions

View File

@ -2,6 +2,7 @@ from __future__ import annotations
import dataclasses import dataclasses
import os import os
from pathlib import Path
import shutil import shutil
import socket import socket
import subprocess import subprocess
@ -87,7 +88,7 @@ class DirectoryBasedController(_BaseController):
"""Helper for controllers whose software configuration is based on an """Helper for controllers whose software configuration is based on an
arbitrary directory.""" arbitrary directory."""
directory: Optional[str] directory: Optional[Path]
def __init__(self, test_config: TestCaseControllerConfig): def __init__(self, test_config: TestCaseControllerConfig):
super().__init__(test_config) super().__init__(test_config)
@ -110,22 +111,21 @@ class DirectoryBasedController(_BaseController):
"""Open a file in the configuration directory.""" """Open a file in the configuration directory."""
assert self.directory assert self.directory
if os.sep in name: if os.sep in name:
dir_ = os.path.join(self.directory, os.path.dirname(name)) dir_ = self.directory / os.path.dirname(name)
if not os.path.isdir(dir_): dir_.mkdir(parents=True, exist_ok=True)
os.makedirs(dir_) assert dir_.is_dir()
assert os.path.isdir(dir_) return (self.directory / name).open(mode)
return open(os.path.join(self.directory, name), mode)
def create_config(self) -> None: def create_config(self) -> None:
if not self.directory: if not self.directory:
self.directory = tempfile.mkdtemp() self.directory = Path(tempfile.mkdtemp())
def gen_ssl(self) -> None: def gen_ssl(self) -> None:
assert self.directory assert self.directory
self.csr_path = os.path.join(self.directory, "ssl.csr") self.csr_path = self.directory / "ssl.csr"
self.key_path = os.path.join(self.directory, "ssl.key") self.key_path = self.directory / "ssl.key"
self.pem_path = os.path.join(self.directory, "ssl.pem") self.pem_path = self.directory / "ssl.pem"
self.dh_path = os.path.join(self.directory, "dh.pem") self.dh_path = self.directory / "dh.pem"
subprocess.check_output( subprocess.check_output(
[ [
self.openssl_bin, self.openssl_bin,

View File

@ -1,4 +1,4 @@
import os from pathlib import Path
import shutil import shutil
import subprocess import subprocess
from typing import Type from typing import Type
@ -101,14 +101,11 @@ class AnopeController(BaseServicesController, DirectoryBasedController):
pass pass
assert self.directory assert self.directory
services_path = shutil.which("services")
assert services_path
# Config and code need to be in the same directory, *obviously* # Config and code need to be in the same directory, *obviously*
os.symlink( (self.directory / "lib").symlink_to(Path(services_path).parent.parent / "lib")
os.path.join(
os.path.dirname(shutil.which("services")), "..", "lib" # type: ignore
),
os.path.join(self.directory, "lib"),
)
self.proc = subprocess.Popen( self.proc = subprocess.Popen(
[ [

View File

@ -1,4 +1,3 @@
import os
import subprocess import subprocess
from typing import Optional, Type from typing import Optional, Type
@ -81,11 +80,11 @@ class AthemeController(BaseServicesController, DirectoryBasedController):
"atheme-services", "atheme-services",
"-n", # don't fork "-n", # don't fork
"-c", "-c",
os.path.join(self.directory, "services.conf"), self.directory / "services.conf",
"-l", "-l",
f"/tmp/services-{server_port}.log", f"/tmp/services-{server_port}.log",
"-p", "-p",
os.path.join(self.directory, "services.pid"), self.directory / "services.pid",
"-D", "-D",
self.directory, self.directory,
], ],

View File

@ -1,4 +1,4 @@
import os from pathlib import Path
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -80,7 +80,7 @@ oper {{
""" """
def initialize_entropy(directory: str) -> None: def initialize_entropy(directory: Path) -> None:
# https://github.com/DALnet/bahamut/blob/7fc039d403f66a954225c5dc4ad1fe683aedd794/include/dh.h#L35-L38 # https://github.com/DALnet/bahamut/blob/7fc039d403f66a954225c5dc4ad1fe683aedd794/include/dh.h#L35-L38
nb_rand_bytes = 512 // 8 nb_rand_bytes = 512 // 8
# https://github.com/DALnet/bahamut/blob/7fc039d403f66a954225c5dc4ad1fe683aedd794/src/dh.c#L186 # https://github.com/DALnet/bahamut/blob/7fc039d403f66a954225c5dc4ad1fe683aedd794/src/dh.c#L186
@ -89,7 +89,7 @@ def initialize_entropy(directory: str) -> None:
# Not actually random; but we don't care. # Not actually random; but we don't care.
entropy = b"\x00" * entropy_file_size entropy = b"\x00" * entropy_file_size
with open(os.path.join(directory, ".ircd.entropy"), "wb") as fd: with (directory / ".ircd.entropy").open("wb") as fd:
fd.write(entropy) fd.write(entropy)
@ -140,8 +140,8 @@ class BahamutController(BaseServerController, DirectoryBasedController):
initialize_entropy(self.directory) initialize_entropy(self.directory)
# they are hardcoded... thankfully Bahamut reads them from the CWD. # they are hardcoded... thankfully Bahamut reads them from the CWD.
shutil.copy(self.pem_path, os.path.join(self.directory, "ircd.crt")) shutil.copy(self.pem_path, self.directory / "ircd.crt")
shutil.copy(self.key_path, os.path.join(self.directory, "ircd.key")) shutil.copy(self.key_path, self.directory / "ircd.key")
with self.open_file("server.conf") as fd: with self.open_file("server.conf") as fd:
fd.write( fd.write(
@ -168,7 +168,7 @@ class BahamutController(BaseServerController, DirectoryBasedController):
"ircd", "ircd",
"-t", # don't fork "-t", # don't fork
"-f", "-f",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
], ],
) )

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set from typing import Optional, Set
@ -88,9 +87,9 @@ class BaseHybridController(BaseServerController, DirectoryBasedController):
self.binary_name, self.binary_name,
"-foreground", "-foreground",
"-configfile", "-configfile",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
"-pidfile", "-pidfile",
os.path.join(self.directory, "server.pid"), self.directory / "server.pid",
], ],
# stderr=subprocess.DEVNULL, # stderr=subprocess.DEVNULL,
) )

View File

@ -185,21 +185,19 @@ class ErgoController(BaseServerController, DirectoryBasedController):
bind_address = "127.0.0.1:%s" % (port,) bind_address = "127.0.0.1:%s" % (port,)
listener_conf = None # plaintext listener_conf = None # plaintext
if ssl: if ssl:
self.key_path = os.path.join(self.directory, "ssl.key") self.key_path = self.directory / "ssl.key"
self.pem_path = os.path.join(self.directory, "ssl.pem") self.pem_path = self.directory / "ssl.pem"
listener_conf = {"tls": {"cert": self.pem_path, "key": self.key_path}} listener_conf = {"tls": {"cert": self.pem_path, "key": self.key_path}}
config["server"]["listeners"][bind_address] = listener_conf # type: ignore config["server"]["listeners"][bind_address] = listener_conf # type: ignore
config["datastore"]["path"] = os.path.join( # type: ignore config["datastore"]["path"] = str(self.directory / "ircd.db") # type: ignore
self.directory, "ircd.db"
)
if password is not None: if password is not None:
config["server"]["password"] = hash_password(password) # type: ignore config["server"]["password"] = hash_password(password) # type: ignore
assert self.proc is None assert self.proc is None
self._config_path = os.path.join(self.directory, "server.yml") self._config_path = self.directory / "server.yml"
self._config = config self._config = config
self._write_config() self._write_config()
subprocess.call(["ergo", "initdb", "--conf", self._config_path, "--quiet"]) subprocess.call(["ergo", "initdb", "--conf", self._config_path, "--quiet"])

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -164,7 +163,7 @@ class InspircdController(BaseServerController, DirectoryBasedController):
"inspircd", "inspircd",
"--nofork", "--nofork",
"--config", "--config",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
], ],
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,
) )

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -68,7 +67,7 @@ class Irc2Controller(BaseServerController, DirectoryBasedController):
self.create_config() self.create_config()
password_field = password if password else "" password_field = password if password else ""
assert self.directory assert self.directory
pidfile = os.path.join(self.directory, "ircd.pid") pidfile = self.directory / "ircd.pid"
with self.open_file("server.conf") as fd: with self.open_file("server.conf") as fd:
fd.write( fd.write(
TEMPLATE_CONFIG.format( TEMPLATE_CONFIG.format(
@ -93,7 +92,7 @@ class Irc2Controller(BaseServerController, DirectoryBasedController):
"-p", "-p",
"on", "on",
"-f", "-f",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
], ],
# stderr=subprocess.DEVNULL, # stderr=subprocess.DEVNULL,
) )

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -87,7 +86,7 @@ class Ircu2Controller(BaseServerController, DirectoryBasedController):
self.create_config() self.create_config()
password_field = 'password = "{}";'.format(password) if password else "" password_field = 'password = "{}";'.format(password) if password else ""
assert self.directory assert self.directory
pidfile = os.path.join(self.directory, "ircd.pid") pidfile = self.directory / "ircd.pid"
with self.open_file("server.conf") as fd: with self.open_file("server.conf") as fd:
fd.write( fd.write(
TEMPLATE_CONFIG.format( TEMPLATE_CONFIG.format(
@ -110,7 +109,7 @@ class Ircu2Controller(BaseServerController, DirectoryBasedController):
"ircd", "ircd",
"-n", # don't detach "-n", # don't detach
"-f", "-f",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
"-x", "-x",
"DEBUG", "DEBUG",
], ],

View File

@ -1,4 +1,3 @@
import os
import subprocess import subprocess
from typing import Optional, Type from typing import Optional, Type
@ -85,9 +84,7 @@ class LimnoriaController(BaseClientController, DirectoryBasedController):
) )
) )
assert self.directory assert self.directory
self.proc = subprocess.Popen( self.proc = subprocess.Popen(["supybot", self.directory / "bot.conf"])
["supybot", os.path.join(self.directory, "bot.conf")]
)
def get_irctest_controller_class() -> Type[LimnoriaController]: def get_irctest_controller_class() -> Type[LimnoriaController]:

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -128,7 +127,7 @@ class MammonController(BaseServerController, DirectoryBasedController):
"mammond", "mammond",
"--nofork", # '--debug', "--nofork", # '--debug',
"--config", "--config",
os.path.join(self.directory, "server.yml"), self.directory / "server.yml",
] ]
) )

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -94,7 +93,7 @@ class NgircdController(BaseServerController, DirectoryBasedController):
password_field=password_field, password_field=password_field,
key_path=self.key_path, key_path=self.key_path,
pem_path=self.pem_path, pem_path=self.pem_path,
empty_file=os.path.join(self.directory, "empty.txt"), empty_file=self.directory / "empty.txt",
) )
) )
@ -110,7 +109,7 @@ class NgircdController(BaseServerController, DirectoryBasedController):
"ngircd", "ngircd",
"--nodaemon", "--nodaemon",
"--config", "--config",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
], ],
# stdout=subprocess.DEVNULL, # stdout=subprocess.DEVNULL,
) )

View File

@ -1,4 +1,3 @@
import os
import shutil import shutil
import subprocess import subprocess
from typing import Optional, Set, Type from typing import Optional, Set, Type
@ -86,7 +85,7 @@ class SnircdController(BaseServerController, DirectoryBasedController):
self.create_config() self.create_config()
password_field = 'password = "{}";'.format(password) if password else "" password_field = 'password = "{}";'.format(password) if password else ""
assert self.directory assert self.directory
pidfile = os.path.join(self.directory, "ircd.pid") pidfile = self.directory / "ircd.pid"
with self.open_file("server.conf") as fd: with self.open_file("server.conf") as fd:
fd.write( fd.write(
TEMPLATE_CONFIG.format( TEMPLATE_CONFIG.format(
@ -109,7 +108,7 @@ class SnircdController(BaseServerController, DirectoryBasedController):
"ircd", "ircd",
"-n", # don't detach "-n", # don't detach
"-f", "-f",
os.path.join(self.directory, "server.conf"), self.directory / "server.conf",
"-x", "-x",
"DEBUG", "DEBUG",
], ],

View File

@ -1,4 +1,4 @@
import os from pathlib import Path
import subprocess import subprocess
import tempfile import tempfile
from typing import Optional, TextIO, Type, cast from typing import Optional, TextIO, Type, cast
@ -38,14 +38,14 @@ class SopelController(BaseClientController):
super().kill() super().kill()
if self.filename: if self.filename:
try: try:
os.unlink(os.path.join(os.path.expanduser("~/.sopel/"), self.filename)) (Path("~/.sopel/").expanduser() / self.filename).unlink()
except OSError: #  File does not exist except OSError: #  File does not exist
pass pass
def open_file(self, filename: str, mode: str = "a") -> TextIO: def open_file(self, filename: str, mode: str = "a") -> TextIO:
dir_path = os.path.expanduser("~/.sopel/") dir_path = Path("~/.sopel/").expanduser()
os.makedirs(dir_path, exist_ok=True) dir_path.mkdir(parents=True, exist_ok=True)
return cast(TextIO, open(os.path.join(dir_path, filename), mode)) return cast(TextIO, (dir_path / filename).open(mode))
def create_config(self) -> None: def create_config(self) -> None:
with self.open_file(self.filename): with self.open_file(self.filename):

View File

@ -5,7 +5,7 @@ import shutil
import signal import signal
import subprocess import subprocess
import textwrap import textwrap
from typing import Optional, Set, Type from typing import List, Optional, Set, Type, Union
from irctest.basecontrollers import ( from irctest.basecontrollers import (
BaseServerController, BaseServerController,
@ -222,20 +222,20 @@ class UnrealircdController(BaseServerController, DirectoryBasedController):
password_field=password_field, password_field=password_field,
key_path=self.key_path, key_path=self.key_path,
pem_path=self.pem_path, pem_path=self.pem_path,
empty_file=os.path.join(self.directory, "empty.txt"), empty_file=self.directory / "empty.txt",
extras=extras, extras=extras,
set_extras=set_extras, set_extras=set_extras,
) )
) )
proot_cmd = [] proot_cmd: List[Union[str, pathlib.Path]] = []
self.using_proot = False self.using_proot = False
if shutil.which("proot"): if shutil.which("proot"):
unrealircd_path = shutil.which("unrealircd") unrealircd_path = shutil.which("unrealircd")
if unrealircd_path: if unrealircd_path:
unrealircd_prefix = pathlib.Path(unrealircd_path).parents[1] unrealircd_prefix = pathlib.Path(unrealircd_path).parents[1]
tmpdir = os.path.join(self.directory, "tmp") tmpdir = self.directory / "tmp"
os.mkdir(tmpdir) tmpdir.mkdir()
# Unreal cleans its tmp/ directory after each run, which prevents # Unreal cleans its tmp/ directory after each run, which prevents
# multiple processes from running at the same time. # multiple processes from running at the same time.
# Using PRoot, we can isolate them, with a tmp/ directory for each # Using PRoot, we can isolate them, with a tmp/ directory for each
@ -258,7 +258,7 @@ class UnrealircdController(BaseServerController, DirectoryBasedController):
"-t", "-t",
"-F", # BOOT_NOFORK "-F", # BOOT_NOFORK
"-f", "-f",
os.path.join(self.directory, "unrealircd.conf"), self.directory / "unrealircd.conf",
], ],
# stdout=subprocess.DEVNULL, # stdout=subprocess.DEVNULL,
) )