Skip to content
Snippets Groups Projects
Commit 58b38f32 authored by Benjamin Schubert's avatar Benjamin Schubert
Browse files

First draft for docker sandbox

parent 2a0676c3
No related branches found
No related tags found
No related merge requests found
Pipeline #39345556 failed
......@@ -63,6 +63,10 @@ class Linux(Platform):
self._linux32 = False
def create_sandbox(self, *args, **kwargs):
# FIXME: we need a better way rather than hijacking
# the normal setup process
from ..sandbox._sandboxdocker import SandboxDocker
return SandboxDocker(*args, **kwargs)
if not self._local_sandbox_available:
return self._create_dummy_sandbox(*args, **kwargs)
else:
......
import os
import sys
import stat
import signal
import subprocess
from contextlib import contextmanager, ExitStack
import psutil
import tempfile
import docker
from .._exceptions import SandboxError
from .. import utils
from .. import _signals
from ._mounter import Mounter
from ._mount import MountMap
from . import Sandbox, SandboxFlags
DOCKERFILE = """
FROM scratch
ADD . /
""".strip()
class SandboxDocker(Sandbox):
def run(self, command, flags, *, cwd=None, env=None):
client = docker.from_env()
stdout, stderr = self._get_output()
# Fallback to the sandbox default settings for
# the cwd and env.
#
cwd = self._get_work_directory(cwd=cwd)
env = self._get_environment(cwd=cwd, env=env)
# Convert single-string argument to a list
if isinstance(command, str):
command = [command]
if not self._has_command(command[0], env):
raise SandboxError("Staged artifacts do not provide command "
"'{}'".format(command[0]),
reason='missing-command')
# Create the mount map, this will tell us where
# each mount point needs to be mounted from and to
mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY)
root_mount_source = mount_map.get_mount_source("/")
with open(os.path.join(root_mount_source, "Dockerfile"), "w") as fp:
fp.write(DOCKERFILE)
image, _ = client.images.build(path=root_mount_source)
volumes = {}
mount_source_overrides = self._get_mount_sources()
for mark in self._get_marked_directories():
mount_point = mark["directory"]
if mount_point in mount_source_overrides:
mount_source = mount_source_overrides[mount_point]
else:
mount_source = mount_map.get_mount_source(mount_point)
volumes[mount_source] = {"bind": mount_point}
# TODO: we need to handle root that is RO
# TODO: we need to handle cwd
# TODO: we need to handle env
# TODO: we need to support specific user uid/gid
# TODO: we need to support interactive mode
args = {
"image": image,
"command": command,
"detach": True,
"volumes": volumes,
}
container = client.containers.run(**args)
# TODO: we need to handle signals and react accordingly
status = container.wait()
self._vdir._mark_changed()
return status["StatusCode"]
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment