[Notes] [Git][BuildStream/buildstream][bschubert/docker-sandbox] First draft for docker sandbox



Title: GitLab

Benjamin Schubert pushed to branch bschubert/docker-sandbox at BuildStream / buildstream

Commits:

2 changed files:

Changes:

  • buildstream/_platform/linux.py
    ... ... @@ -59,6 +59,10 @@ class Linux(Platform):
    59 59
                 self._user_ns_available = False
    
    60 60
     
    
    61 61
         def create_sandbox(self, *args, **kwargs):
    
    62
    +        # FIXME: we need a better way rather than hijacking
    
    63
    +        #        the normal setup process
    
    64
    +        from ..sandbox._sandboxdocker import SandboxDocker
    
    65
    +        return SandboxDocker(*args, **kwargs)
    
    62 66
             if not self._local_sandbox_available:
    
    63 67
                 return self._create_dummy_sandbox(*args, **kwargs)
    
    64 68
             else:
    

  • buildstream/sandbox/_sandboxdocker.py
    1
    +import os
    
    2
    +import sys
    
    3
    +import stat
    
    4
    +import signal
    
    5
    +import subprocess
    
    6
    +from contextlib import contextmanager, ExitStack
    
    7
    +import psutil
    
    8
    +import tempfile
    
    9
    +
    
    10
    +import docker
    
    11
    +
    
    12
    +from .._exceptions import SandboxError
    
    13
    +from .. import utils
    
    14
    +from .. import _signals
    
    15
    +from ._mounter import Mounter
    
    16
    +from ._mount import MountMap
    
    17
    +from . import Sandbox, SandboxFlags
    
    18
    +
    
    19
    +
    
    20
    +DOCKERFILE = """
    
    21
    +FROM scratch
    
    22
    +
    
    23
    +ADD . /
    
    24
    +""".strip()
    
    25
    +
    
    26
    +
    
    27
    +class SandboxDocker(Sandbox):
    
    28
    +
    
    29
    +    def run(self, command, flags, *, cwd=None, env=None):
    
    30
    +        client = docker.from_env()
    
    31
    +        stdout, stderr = self._get_output()
    
    32
    +
    
    33
    +        # Fallback to the sandbox default settings for
    
    34
    +        # the cwd and env.
    
    35
    +        #
    
    36
    +        cwd = self._get_work_directory(cwd=cwd)
    
    37
    +        env = self._get_environment(cwd=cwd, env=env)
    
    38
    +
    
    39
    +        # Convert single-string argument to a list
    
    40
    +        if isinstance(command, str):
    
    41
    +            command = [command]
    
    42
    +
    
    43
    +        if not self._has_command(command[0], env):
    
    44
    +            raise SandboxError("Staged artifacts do not provide command "
    
    45
    +                               "'{}'".format(command[0]),
    
    46
    +                               reason='missing-command')
    
    47
    +
    
    48
    +        # Create the mount map, this will tell us where
    
    49
    +        # each mount point needs to be mounted from and to
    
    50
    +        mount_map = MountMap(self, flags & SandboxFlags.ROOT_READ_ONLY)
    
    51
    +        root_mount_source = mount_map.get_mount_source("/")
    
    52
    +
    
    53
    +        with open(os.path.join(root_mount_source, "Dockerfile"), "w") as fp:
    
    54
    +            fp.write(DOCKERFILE)
    
    55
    +
    
    56
    +        image, _ = client.images.build(path=root_mount_source)
    
    57
    +
    
    58
    +        volumes = {}
    
    59
    +
    
    60
    +        mount_source_overrides = self._get_mount_sources()
    
    61
    +        for mark in self._get_marked_directories():
    
    62
    +            mount_point = mark["directory"]
    
    63
    +            if mount_point in mount_source_overrides:
    
    64
    +                mount_source = mount_source_overrides[mount_point]
    
    65
    +            else:
    
    66
    +                mount_source = mount_map.get_mount_source(mount_point)
    
    67
    +
    
    68
    +            volumes[mount_source] = {"bind": mount_point}
    
    69
    +
    
    70
    +        # TODO: we need to handle root that is RO
    
    71
    +        # TODO: we need to handle cwd
    
    72
    +        # TODO: we need to handle env
    
    73
    +        # TODO: we need to support specific user uid/gid
    
    74
    +        # TODO: we need to support interactive mode
    
    75
    +        args = {
    
    76
    +            "image": image,
    
    77
    +            "command": command,
    
    78
    +            "detach": True,
    
    79
    +            "volumes": volumes,
    
    80
    +        }
    
    81
    +
    
    82
    +        container = client.containers.run(**args)
    
    83
    +        # TODO: we need to handle signals and react accordingly
    
    84
    +        status = container.wait()
    
    85
    +
    
    86
    +        self._vdir._mark_changed()
    
    87
    +        return status["StatusCode"]



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]