Rename container_runtime to container_engine

This is mainly to be able to handle runtime-related features in
following commits.
This commit is contained in:
Alexis Métaireau 2024-06-25 19:07:11 +02:00
parent c2a47ec46b
commit 33ab2454b8
No known key found for this signature in database
GPG key ID: C65C7A89A8FFC56E
3 changed files with 36 additions and 32 deletions

View file

@ -18,7 +18,8 @@ from .base import PIXELS_TO_PDF_LOG_END, PIXELS_TO_PDF_LOG_START, IsolationProvi
# Define startupinfo for subprocesses # Define startupinfo for subprocesses
if platform.system() == "Windows": if platform.system() == "Windows":
startupinfo = subprocess.STARTUPINFO() # type: ignore [attr-defined] startupinfo = subprocess.STARTUPINFO() # type: ignore [attr-defined]
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW # type: ignore [attr-defined] # type: ignore [attr-defined]
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else: else:
startupinfo = None startupinfo = None
@ -36,16 +37,16 @@ class Container(IsolationProvider):
CONTAINER_NAME = "dangerzone.rocks/dangerzone" CONTAINER_NAME = "dangerzone.rocks/dangerzone"
@staticmethod @staticmethod
def get_runtime_name() -> str: def get_container_engine_name() -> str:
if platform.system() == "Linux": if platform.system() == "Linux":
runtime_name = "podman" container_engine = "podman"
else: else:
# Windows, Darwin, and unknown use docker for now, dangerzone-vm eventually # Windows, Darwin, and unknown use docker for now, dangerzone-vm eventually
runtime_name = "docker" container_engine = "docker"
return runtime_name return container_engine
@staticmethod @staticmethod
def get_runtime_version() -> Tuple[int, int]: def get_container_engine_version() -> Tuple[int, int]:
"""Get the major/minor parts of the Docker/Podman version. """Get the major/minor parts of the Docker/Podman version.
Some of the operations we perform in this module rely on some Podman features Some of the operations we perform in this module rely on some Podman features
@ -55,14 +56,14 @@ class Container(IsolationProvider):
semver parser is an overkill. semver parser is an overkill.
""" """
# Get the Docker/Podman version, using a Go template. # Get the Docker/Podman version, using a Go template.
runtime = Container.get_runtime_name() container_engine = Container.get_container_engine_name()
cmd = [runtime, "version", "-f", "{{.Client.Version}}"] cmd = [container_engine, "version", "-f", "{{.Client.Version}}"]
try: try:
version = subprocess.run( version = subprocess.run(
cmd, capture_output=True, check=True cmd, capture_output=True, check=True
).stdout.decode() ).stdout.decode()
except Exception as e: except Exception as e:
msg = f"Could not get the version of the {runtime.capitalize()} tool: {e}" msg = f"Could not get the version of the {container_engine.capitalize()} tool: {e}"
raise RuntimeError(msg) from e raise RuntimeError(msg) from e
# Parse this version and return the major/minor parts, since we don't need the # Parse this version and return the major/minor parts, since we don't need the
@ -72,18 +73,18 @@ class Container(IsolationProvider):
return (int(major), int(minor)) return (int(major), int(minor))
except Exception as e: except Exception as e:
msg = ( msg = (
f"Could not parse the version of the {runtime.capitalize()} tool" f"Could not parse the version of the {container_engine.capitalize()} tool"
f" (found: '{version}') due to the following error: {e}" f" (found: '{version}') due to the following error: {e}"
) )
raise RuntimeError(msg) raise RuntimeError(msg)
@staticmethod @staticmethod
def get_runtime() -> str: def get_container_engine() -> str:
container_tech = Container.get_runtime_name() container_name = Container.get_container_engine_name()
runtime = shutil.which(container_tech) container_engine = shutil.which(container_name)
if runtime is None: if container_engine is None:
raise NoContainerTechException(container_tech) raise NoContainerTechException(container_name)
return runtime return container_engine
@staticmethod @staticmethod
def get_runtime_security_args() -> List[str]: def get_runtime_security_args() -> List[str]:
@ -104,7 +105,7 @@ class Container(IsolationProvider):
- This particular argument is specified in `start_doc_to_pixels_proc()`, but - This particular argument is specified in `start_doc_to_pixels_proc()`, but
should move here once #748 is merged. should move here once #748 is merged.
""" """
if Container.get_runtime_name() == "podman": if Container.get_container_engine_name() == "podman":
security_args = ["--log-driver", "none"] security_args = ["--log-driver", "none"]
security_args += ["--security-opt", "no-new-privileges"] security_args += ["--security-opt", "no-new-privileges"]
@ -114,9 +115,10 @@ class Container(IsolationProvider):
# This file has been copied as is [1] from the official Podman repo. # This file has been copied as is [1] from the official Podman repo.
# #
# [1] https://github.com/containers/common/blob/d3283f8401eeeb21f3c59a425b5461f069e199a7/pkg/seccomp/seccomp.json # [1] https://github.com/containers/common/blob/d3283f8401eeeb21f3c59a425b5461f069e199a7/pkg/seccomp/seccomp.json
if Container.get_runtime_version() < (4, 0): if Container.get_container_engine_version() < (4, 0):
seccomp_json_path = get_resource_path("seccomp.gvisor.json") seccomp_json_path = get_resource_path("seccomp.gvisor.json")
security_args += ["--security-opt", f"seccomp={seccomp_json_path}"] security_args += ["--security-opt",
f"seccomp={seccomp_json_path}"]
else: else:
security_args = ["--security-opt=no-new-privileges:true"] security_args = ["--security-opt=no-new-privileges:true"]
@ -140,7 +142,7 @@ class Container(IsolationProvider):
log.info("Installing Dangerzone container image...") log.info("Installing Dangerzone container image...")
p = subprocess.Popen( p = subprocess.Popen(
[Container.get_runtime(), "load"], [Container.get_container_engine(), "load"],
stdin=subprocess.PIPE, stdin=subprocess.PIPE,
startupinfo=get_subprocess_startupinfo(), startupinfo=get_subprocess_startupinfo(),
) )
@ -177,7 +179,7 @@ class Container(IsolationProvider):
installed = False installed = False
found_image_id = subprocess.check_output( found_image_id = subprocess.check_output(
[ [
Container.get_runtime(), Container.get_container_engine(),
"image", "image",
"list", "list",
"--format", "--format",
@ -198,11 +200,13 @@ class Container(IsolationProvider):
try: try:
subprocess.check_output( subprocess.check_output(
[Container.get_runtime(), "rmi", "--force", found_image_id], [Container.get_container_engine(), "rmi", "--force",
found_image_id],
startupinfo=get_subprocess_startupinfo(), startupinfo=get_subprocess_startupinfo(),
) )
except Exception: except Exception:
log.warning("Couldn't delete old container image, so leaving it there") log.warning(
"Couldn't delete old container image, so leaving it there")
return installed return installed
@ -260,7 +264,7 @@ class Container(IsolationProvider):
name: str, name: str,
extra_args: List[str] = [], extra_args: List[str] = [],
) -> subprocess.Popen: ) -> subprocess.Popen:
container_runtime = self.get_runtime() container_runtime = self.get_container_engine()
security_args = self.get_runtime_security_args() security_args = self.get_runtime_security_args()
enable_stdin = ["-i"] enable_stdin = ["-i"]
set_name = ["--name", name] set_name = ["--name", name]
@ -288,7 +292,7 @@ class Container(IsolationProvider):
connected to the Docker daemon, and killing it will just close the associated connected to the Docker daemon, and killing it will just close the associated
standard streams. standard streams.
""" """
container_runtime = self.get_runtime() container_runtime = self.get_container_engine()
cmd = [container_runtime, "kill", name] cmd = [container_runtime, "kill", name]
try: try:
# We do not check the exit code of the process here, since the container may # We do not check the exit code of the process here, since the container may
@ -391,8 +395,8 @@ class Container(IsolationProvider):
# NOTE: Using `--userns nomap` is available only on Podman >= 4.1.0. # NOTE: Using `--userns nomap` is available only on Podman >= 4.1.0.
# XXX: Move this under `get_runtime_security_args()` once #748 is merged. # XXX: Move this under `get_runtime_security_args()` once #748 is merged.
extra_args = [] extra_args = []
if Container.get_runtime_name() == "podman": if Container.get_container_engine_name() == "podman":
if Container.get_runtime_version() >= (4, 1): if Container.get_container_engine_version() >= (4, 1):
extra_args += ["--userns", "nomap"] extra_args += ["--userns", "nomap"]
name = self.doc_to_pixels_container_name(document) name = self.doc_to_pixels_container_name(document)
@ -419,7 +423,7 @@ class Container(IsolationProvider):
# after a podman kill / docker kill invocation, this will likely be the case, # after a podman kill / docker kill invocation, this will likely be the case,
# else the container runtime (Docker/Podman) has experienced a problem, and we # else the container runtime (Docker/Podman) has experienced a problem, and we
# should report it. # should report it.
container_runtime = self.get_runtime() container_runtime = self.get_container_engine()
name = self.doc_to_pixels_container_name(document) name = self.doc_to_pixels_container_name(document)
all_containers = subprocess.run( all_containers = subprocess.run(
[container_runtime, "ps", "-a"], [container_runtime, "ps", "-a"],
@ -441,11 +445,11 @@ class Container(IsolationProvider):
if cpu_count is not None: if cpu_count is not None:
n_cpu = cpu_count n_cpu = cpu_count
elif self.get_runtime_name() == "docker": elif self.get_container_engine_name() == "docker":
# For Windows and MacOS containers run in VM # For Windows and MacOS containers run in VM
# So we obtain the CPU count for the VM # So we obtain the CPU count for the VM
n_cpu_str = subprocess.check_output( n_cpu_str = subprocess.check_output(
[self.get_runtime(), "info", "--format", "{{.NCPU}}"], [self.get_container_engine(), "info", "--format", "{{.NCPU}}"],
text=True, text=True,
startupinfo=get_subprocess_startupinfo(), startupinfo=get_subprocess_startupinfo(),
) )

View file

@ -22,7 +22,7 @@ class ContainerWait(Container):
# Check every 100ms if a container with the expected name has showed up. # Check every 100ms if a container with the expected name has showed up.
# Else, closing the file descriptors may not work. # Else, closing the file descriptors may not work.
name = kwargs["name"] name = kwargs["name"]
runtime = self.get_runtime() runtime = self.get_container_engine()
p = super().exec_container(*args, **kwargs) p = super().exec_container(*args, **kwargs)
for i in range(50): for i in range(50):
containers = subprocess.run( containers = subprocess.run(

View file

@ -16,7 +16,7 @@ from dangerzone.logic import DangerzoneCore
def test_ocr_ommisions() -> None: def test_ocr_ommisions() -> None:
# Create the command that will list all the installed languages in the container # Create the command that will list all the installed languages in the container
# image. # image.
command = [Container.get_runtime(), "run"] command = [Container.get_container_engine(), "run"]
command += Container.get_runtime_security_args() command += Container.get_runtime_security_args()
command += [ command += [
Container.CONTAINER_NAME, Container.CONTAINER_NAME,