Example #1
0
    def _run_docker_container(self, runflags):
        """
        Create & run job container, install klio packages as editable,
        and attach to the container with an interactive terminal.
        """
        container = self._docker_client.containers.create(**runflags)
        container.start()

        def run_and_log(cmd):
            _, output = container.exec_run(cmd, tty=True, stream=True)
            for line in output:
                try:
                    self._docker_logger.info(line.decode("utf-8").strip("\n"))
                except Exception:
                    # sometimes there's a decode error for a log line, but it
                    # shouldn't stop the setup
                    pass

        run_and_log("pip install --upgrade pip setuptools")
        for pkg in self.install_pkgs:
            run_and_log(self.PIP_CMD.format(pkg=pkg))

        # need to use lower-level Docker API client in order to start
        # an interactive terminal inside the running container
        self._docker_logger.info(
            "\nConnecting to job's container. Use CTRL+C to stop.")
        pty_client = docker.APIClient(base_url="unix://var/run/docker.sock")
        dockerpty.start(pty_client, container.attrs)
Example #2
0
 def start(self, projectname):
     dataMap = self.get_settings()
     current_directory = os.getcwd()
     data_folder = Path("osdp")
     file_to_open = data_folder / "projects" / dataMap['osdp']['project'] / dataMap['osdp']['platform']
     final_directory = os.path.join(current_directory, file_to_open)
     if not os.path.exists(final_directory):
         print("This should have already been created")
         exit()
     if dataMap['osdp']['platform'] == 'vagrant':
         vagrant_folder = Path(final_directory)
         v = vagrant.Vagrant(vagrant_folder, quiet_stdout=False)
         try:
             v.up()
         except Exception as e:
             pass
         os.chdir(vagrant_folder)
         cmdCommand = "vagrant port"
         process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)
         output, error = process.communicate()
         print(output)
     elif dataMap['osdp']['platform'] == 'docker':
         print("Ths platform is docker and we will connect to the image")
         os.chdir(final_directory)
         retval = os.getcwd()
         IMG_SRC = dataMap['osdp']['dockerdeveloperimage']
         client = docker.Client()
         client.login(username=dataMap['osdp']['dockerhubusername'], password=dataMap['osdp']['dockerhubpassword'], registry="https://index.docker.io/v1/")
         client.pull(IMG_SRC)
         client.tag(image=dataMap['osdp']['dockerdeveloperimage'], repository=dataMap['osdp']['pushto'],tag=dataMap['osdp']['runtime'])
         response = [line for line in client.push(dataMap['osdp']['pushto'] + ":" + dataMap['osdp']['runtime'], stream=True)]
         container_id = client.create_container('buildmystartup/ghettolabs:python3.6',stdin_open=True,tty=True,command='/bin/bash', volumes=['/home/user/environments/osdp/osdp/projects/ghettolabs/docker'],host_config=client.create_host_config \
         (binds=['/home/user/environments/osdp/osdp/projects/ghettolabs/docker:/var/task',]))
         dockerpty.start(client, container_id)
Example #3
0
def step_impl(ctx):
    pid, fd = pty.fork()

    if pid == pty.CHILD:
        tty = os.ttyname(0)
        sys.stdin = open(tty, 'r')
        sys.stdout = open(tty, 'w')
        sys.stderr = open(tty, 'w')

        try:
            dockerpty.start(ctx.client, ctx.container)
        except Exception as e:
            raise e
            os._exit(1)
        else:
            os._exit(0)
    else:
        tty = os.ttyname(fd)
        ctx.pty = fd
        util.set_pty_size(
            ctx.pty,
            (ctx.rows, ctx.cols)
        )
        ctx.pid = pid
        util.wait(ctx.pty, timeout=5)
Example #4
0
    def resurrect_shell(self, container=None, env=None):
        if container is None:
            container = self.current_task.container
            if env is None:
                env = self.current_task.env

        # once the command is stopped, there's no getting it back without
        # running the command again, but we can commit to an image
        image = container.commit(
            changes="LABEL {}={}".format(LABEL_BUILD_ID, "@temporary")
        )
        self._extra_images.append(image)

        try:
            container = self.docker_client.containers.create(
                image=image,
                labels={LABEL_BUILD_ID: "@temporary"},
                working_dir=self.work_dir,
                stdin_open=True,
                environment=["{}={}".format(*p) for p in env.items()],
                tty=True,
                command="/bin/bash"  # XXX This is a guess!
            )
            self._all_containers.append(container)

            try:
                dockerpty.start(self.docker_client.api, container.id)
            finally:
                container.stop()
        finally:
            self.cleanup()
def step_impl(ctx):
    pid, fd = pty.fork()

    if pid == pty.CHILD:
        tty = os.ttyname(0)
        sys.stdin = open(tty, 'r')
        sys.stdout = open(tty, 'w')
        sys.stderr = open(tty, 'w')

        try:
            dockerpty.start(ctx.client, ctx.container)
        except Exception as e:
            raise e
            os._exit(1)
        else:
            os._exit(0)
    else:
        tty = os.ttyname(fd)
        ctx.pty = fd
        util.set_pty_size(
            ctx.pty,
            (ctx.rows, ctx.cols)
        )
        ctx.pid = pid
        util.wait(ctx.pty, timeout=5)
    time.sleep(1) # give the terminal some time to print prompt
Example #6
0
    def run_command(self, command):
        # type: (str) -> None
        if self.shell:
            to_run = shlex.split(
                self.shell) + [command]  # type: Union[str, List[str]]
            console.progress("(%s)> %s" % (self.shell, command))
        else:
            to_run = command
            console.progress("> %s" % command)

        container = self.service.create_container(one_off=True,
                                                  command=to_run,
                                                  tty=False,
                                                  stdin_open=True,
                                                  detach=False)

        try:
            dockerpty.start(self.client, container.id, interactive=False)

            if container.wait() != 0:
                raise BuildFailedException()
                sys.exit(1)

        finally:
            self.client.remove_container(container.id, force=True)
Example #7
0
File: main.py Project: tristanz/fig
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ fig run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `fig run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] SERVICE [COMMAND] [ARGS...]

        Options:
            -d         Detached mode: Run container in the background, print
                       new container name.
            -T         Disable pseudo-tty allocation. By default `fig run`
                       allocates a TTY.
            --rm       Remove container after run. Ignored in detached mode.
            --no-deps  Don't start linked services.
        """
        service = project.get_service(options['SERVICE'])

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_links=True,
                    recreate=False,
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
        }
        container = service.create_container(one_off=True, **container_options)
        if options['-d']:
            service.start_container(container, ports=None, one_off=True)
            print(container.name)
        else:
            service.start_container(container, ports=None, one_off=True)
            dockerpty.start(project.client, container.id)
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #8
0
 def __call__(self, *args, **kwargs):
     cli = self.swarm.client
     if cli is not None:
         rm_flag = kwargs.pop('rm')
         logs = kwargs.pop('logs')
         try:
             ret = cli.create_container(*args, **kwargs)
             if ret.get('Warnings') is not None:
                 print('[Warning] {message}'.format(message=ret['Warnings']))
             # try to start created container
             if ret.get('Id') is not None:
                 if kwargs['stdin_open'] and kwargs['tty']:
                     dockerpty.start(cli, ret['Id'], logs=logs)
                 else:
                     cli.start(ret['Id'])
                     print(ret['Id'])
                 if rm_flag:
                     cli.remove_container(ret['Id'])
         except (errors.NotFound, errors.APIError, errors.DockerException) as e:
             pyprint(e.explanation)
         # volumes_from and dns arguments raise TypeError exception 
         # if they are used against v1.10 and above of the Docker remote API
         except TypeError as e:
             pyprint(e)
         finally:
             cli.close()
Example #9
0
def debug(arg_list):
    cwd = os.getcwd()
    cli = get_cli()
    image_name = "%s:%s" % (container_repo, container_tag())
    bind_dirs = mount_volumes()

    container_data = cli.create_container(image=image_name,
                                          command=arg_list,
                                          host_config=cli.create_host_config(
                                              port_bindings={3333:3333},
                                              network_mode='host',
                                              binds=bind_dirs
                                          ),
                                          working_dir=cwd,
                                          tty=True,
                                          stdin_open=True,
                                          ports=[3333])

    container_id = container_data['Id'].encode('utf8')

    if container_data['Warnings']:
        print "Warnings: ", container_data['Warnings']
    if sys.platform.startswith('darwin'):
        darwin_debug(arg_list, bind_dirs)
    else:
        dockerpty.start(cli, container_id)
        cli.stop(container_id)
        cli.remove_container(container_id)
Example #10
0
def install():
    loader = PackageLoader()
    package = loader.load(os.getcwd())

    client_factory = DockerClientFactory()
    client = client_factory.get_client()

    container = client.create_container(
        image=package.current_image,
        stdin_open=True,
        tty=True,
        command="pip install flask",
        working_dir=MOUNT_DIRECTORY,
        host_config=client.create_host_config(binds={
            os.getcwd(): {
                "bind": MOUNT_DIRECTORY,
                "mode": "rw"
            }
        })
    )

    dockerpty.start(client, container)

    # Update package image
    package.current_image = client.commit(container.get("Id")).get("Id")
    loader.save(os.getcwd(), package)
Example #11
0
def step_impl(ctx):
    pid, fd = pty.fork()

    if pid == pty.CHILD:
        tty = os.ttyname(0)
        sys.stdin = open(tty, 'r')
        sys.stdout = open(tty, 'w')
        sys.stderr = open(tty, 'w')

        try:
            dockerpty.start(ctx.client, ctx.container)
        except Exception as e:
            raise e
            os._exit(1)
        else:
            os._exit(0)
    else:
        try:
            tty = os.ttyname(fd)
        except OSError as ex:
            # Not supported on OS X. But since we're not using this
            # TTY name anyway, let the test pass.
            tty = 'OSX'
        ctx.pty = fd
        util.set_pty_size(
            ctx.pty,
            (ctx.rows, ctx.cols)
        )
        ctx.pid = pid
        util.wait(ctx.pty, timeout=5)
    time.sleep(1) # give the terminal some time to print prompt
Example #12
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ fig run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `fig run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] SERVICE [COMMAND] [ARGS...]

        Options:
            -d         Detached mode: Run container in the background, print
                       new container name.
            -T         Disable pseudo-tty allocation. By default `fig run`
                       allocates a TTY.
            --rm       Remove container after run. Ignored in detached mode.
            --no-deps  Don't start linked services.
        """
        service = project.get_service(options['SERVICE'])

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_links=True,
                    recreate=False,
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
        }
        container = service.create_container(one_off=True, **container_options)
        if options['-d']:
            service.start_container(container, ports=None, one_off=True)
            print(container.name)
        else:
            service.start_container(container, ports=None, one_off=True)
            dockerpty.start(project.client, container.id)
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #13
0
    def attach(self):
        if not self.container():
            sys.stderr.write("Error:  container does not exist\n")
            sys.exit(1)

        dockerpty.start(
            self.c,
            self.c.inspect_container(self.config.hostname))
Example #14
0
 def eval_command(self, args):
     """Start containers"""
     if (args["detach"] is False) and (args["tty"]):
         dockerpty.start(self.client,
                         self.settings["create"],
                         interactive=args["stdin_open"])
     else:
         self.client.start(self.settings["create"])
Example #15
0
 def _start(self):
     self._log.info("Starting container: {0}".format(self._cobj.id))
     if self._isatty():
         dockerpty.start(self._dc.api, self._cobj.id)
     else:
         self._cobj.start()
     ret = self._cobj.wait()
     self._log.info("Container {0} stopped and returned {1}".format(self._cobj.id,
                                                                    ret['StatusCode']))
Example #16
0
def docker_run(
    docker_client,
    image_id,
    command,
    project_root,
    environment_variables,
    platform_config_paths=[],
):
    exit_status = 0
    output = 'Done'
    try:
        volumes = {
            project_root: {
                'bind': project_root,
                'mode': 'rw',
            },
            '/var/run/docker.sock': {
                'bind': '/var/run/docker.sock',
                'mode': 'ro',
            }
        }
        for platform_config_path in platform_config_paths:
            volumes[platform_config_path] = {
                'bind': platform_config_path,
                'mode': 'ro',
            }
        if _command(command) == 'shell':
            columns = int(check_output(['tput', 'cols']))
            lines = int(check_output(['tput', 'lines']))
            environment_variables['COLUMNS'] = columns
            environment_variables['LINES'] = lines
            container = docker_client.containers.create(
                image_id,
                command=command,
                environment=environment_variables,
                volumes=volumes,
                working_dir=project_root,
                tty=True,
                stdin_open=True,
            )
            dockerpty.start(docker_client.api, container.id)
            output = 'Shell end'
        else:
            container = docker_client.containers.run(
                image_id,
                command=command,
                environment=environment_variables,
                detach=True,
                volumes=volumes,
                working_dir=project_root,
            )
            _print_logs(container)
            return handle_finished_container(container)
    except DockerException as error:
        exit_status = 1
        output = str(error)
    return exit_status, output
def detection():
    path = current_directory + '/detection/'
    name = 'crosswalk_detection'
    volume = current_directory + 'crosswalks:/crosswalks/'
    build_container_if_not_exist(path, name + ':latest')
    if shutil.which('nvidia-docker'):
        remove_container_if_exist(name)
        subprocess.run('nvidia-docker run -it -v ' + volume + ' -t ' + name + ' ' + name + ' bash')
    else:
        container = create_container_if_not_exist(image=name, volumes=volume, name=name, tty=True, stdin_open=True)
        dockerpty.start(client, container)
Example #18
0
def run_one_off_container(container_options, project, service, options):
    if not options['--no-deps']:
        deps = service.get_linked_service_names()
        if deps:
            project.up(
                service_names=deps,
                start_deps=True,
                strategy=ConvergenceStrategy.never)

    if project.use_networking:
        project.ensure_network_exists()

    try:
        container = service.create_container(
            quiet=True,
            one_off=True,
            **container_options)
    except APIError:
        legacy.check_for_legacy_containers(
            project.client,
            project.name,
            [service.name],
            allow_one_off=False)
        raise

    if options['-d']:
        container.start()
        print(container.name)
        return

    def remove_container(force=False):
        if options['--rm']:
            project.client.remove_container(container.id, force=True)

    def force_shutdown(signal, frame):
        project.client.kill(container.id)
        remove_container(force=True)
        sys.exit(2)

    def shutdown(signal, frame):
        set_signal_handler(force_shutdown)
        project.client.stop(container.id)
        remove_container()
        sys.exit(1)

    set_signal_handler(shutdown)
    dockerpty.start(project.client, container.id, interactive=not options['-T'])
    exit_code = container.wait()
    remove_container()
    sys.exit(exit_code)
Example #19
0
 def _run_interactive_container(self, image, docker_args, container_id):
     try:
         docker_container = self.docker_client.containers.create(
             image, **docker_args)
         self.printer.print_launch_container(container_id,
                                             launched_ok=True,
                                             is_interactive=True)
         dockerpty.start(self.docker_client.api, docker_container.id)
         self.printer.print_stop_container(container_id, stopped_ok=True)
     except Exception as e:
         self.printer.print_launch_container(container_id,
                                             launched_ok=False,
                                             is_interactive=True)
         self.printer.print_error("{}".format(e))
         return
def sandbox_file_in_container(image, command, file_path):
    if not docker_client.images(name=image):
        """empty"""
        docker_client.pull(image)

    directory = _find_dir(str(file_path))
    image = docker_client.create_container(image=image, working_dir=directory,
                                           volumes=[directory],
                                           host_config=docker_client.create_host_config(binds=[
                                                   directory + ':' + directory,
                                               ]),
                                           stdin_open=True, tty=True,
                                           command=command)
    dockerpty.start(docker_client, image)
    docker_client.remove_container(image)
Example #21
0
def run_one_off_container(container_options, project, service, options):
    if not options['--no-deps']:
        deps = service.get_linked_service_names()
        if deps:
            project.up(service_names=deps,
                       start_deps=True,
                       strategy=ConvergenceStrategy.never)

    if project.use_networking:
        project.ensure_network_exists()

    try:
        container = service.create_container(quiet=True,
                                             one_off=True,
                                             **container_options)
    except APIError:
        legacy.check_for_legacy_containers(project.client,
                                           project.name, [service.name],
                                           allow_one_off=False)
        raise

    if options['-d']:
        container.start()
        print(container.name)
        return

    def remove_container(force=False):
        if options['--rm']:
            project.client.remove_container(container.id, force=True)

    def force_shutdown(signal, frame):
        project.client.kill(container.id)
        remove_container(force=True)
        sys.exit(2)

    def shutdown(signal, frame):
        set_signal_handler(force_shutdown)
        project.client.stop(container.id)
        remove_container()
        sys.exit(1)

    set_signal_handler(shutdown)
    dockerpty.start(project.client,
                    container.id,
                    interactive=not options['-T'])
    exit_code = container.wait()
    remove_container()
    sys.exit(exit_code)
Example #22
0
def detection():
    path = current_directory + '/detection/'
    name = 'crosswalk_detection'
    volume = current_directory + 'crosswalks:/crosswalks/'
    build_container_if_not_exist(path, name + ':latest')
    if shutil.which('nvidia-docker'):
        remove_container_if_exist(name)
        subprocess.run('nvidia-docker run -it -v ' + volume + ' -t ' + name +
                       ' ' + name + ' bash')
    else:
        container = create_container_if_not_exist(image=name,
                                                  volumes=volume,
                                                  name=name,
                                                  tty=True,
                                                  stdin_open=True)
        dockerpty.start(client, container)
Example #23
0
    def run_pty(
            self,
            image: str,
            *,  # enforce the rest as kwargs
            command: str = DEFAULT_PTY_COMMAND,
            environment: Optional[List[models.Environment]] = None,
            network: Optional[str] = None,
            ports: Optional[List[models.Port]] = None,
            remove: bool = True,
            volumes: Optional[List[models.Volume]] = None):
        """
        Runs a docker container and spawns an interactive shell over a pseudo terminal.

        Args:
            image: The docker container will be built from this image
            command: The command to run on the docker container.  This command should spawn
                a shell and defaults to /bin/bash
            environment: List of environment variables that the container will use
            network: The network that the container will connect to
            ports: List of ports that the container will expose
            remove: Removes container after running the command, defaults to True
            volumes: List of volumes that the container will mount
        """
        try:
            container = self._docker_client.containers.create(
                image=image,
                command=command,
                volumes=_volume_strings_from_collection(volumes),
                environment=_environment_from_collection(environment),
                network_mode=network,
                ports=_port_bindings_from_collection(ports),
                tty=True,
                stdin_open=True,
            )
        except docker.errors.DockerException as e:
            raise ContainerError(
                "Unable to create container: {}".format(e)) from e

        # Attempt to start docker pty
        try:
            dockerpty.start(self._docker_client.api, {"Id": container.id})
        except Exception as e:
            raise ContainerPtyError(
                "Unable to start a PTY terminal: {}".format(e)) from e
        finally:
            if remove:
                _remove_container(container)
Example #24
0
    def run_command(self, command):
        console.progress("> %s" % command)

        container = self.service.create_container(one_off=True,
                                                  command=command,
                                                  tty=False,
                                                  stdin_open=True,
                                                  detach=False)

        try:
            dockerpty.start(self.client, container.id, interactive=False)

            if container.wait() != 0:
                console.error("\nBuild Failed.")
                sys.exit(1)

        finally:
            self.client.remove_container(container.id, force=True)
Example #25
0
    def start(self, projectname):
        dataMap = self.get_settings()
        current_directory = os.getcwd()
        data_folder = Path("osdp")
        file_to_open = data_folder / "projects" / dataMap['osdp'][
            'project'] / dataMap['osdp']['platform']
        self.final_directory = os.path.join(current_directory, file_to_open)
        if not os.path.exists(self.final_directory):
            print("This should have already been created")
            self.build()
        if dataMap['osdp']['platform'] == 'vagrant':
            messages.send_message(
                dataMap['osdp']['username'] + " " +
                "Just started a vagrant box for Python Development")
            vagrant_folder = Path(self.final_directory)
            v = vagrant.Vagrant(vagrant_folder, quiet_stdout=False)
            try:
                v.up()
            except Exception as e:
                print("Please open a github issue if you have a problem")
            os.chdir(vagrant_folder)
            cmdCommand = "vagrant port"
            process = subprocess.Popen(cmdCommand.split(),
                                       stdout=subprocess.PIPE)
            output, error = process.communicate()
            print(output)
            subprocess.run(["vagrant", "ssh"])
        elif dataMap['osdp']['platform'] == 'docker':
            print("Ths platform is docker and we will connect to the image")
            os.chdir(self.final_directory)
            retval = os.getcwd()
            IMG_SRC = dataMap['osdp']['dockerdeveloperimage']
            client = docker.Client()
            # Uncomment if working with a private image
            #client.login(username=dataMap['osdp']['dockerhubusername'], password=dataMap['osdp']['dockerhubpassword'], registry="https://index.docker.io/v1/")
            client.pull(IMG_SRC)
            #client.tag(image=dataMap['osdp']['dockerdeveloperimage'], repository=dataMap['osdp']['pushto'],tag=dataMap['osdp']['runtime'])
            #response = [line for line in client.push(dataMap['osdp']['pushto'] + ":" + dataMap['osdp']['runtime'], stream=True)]
            container_id = client.create_container(dataMap['osdp']['imagename'],stdin_open=True,tty=True,command='/bin/bash', volumes=dataMap['osdp']['dockerhome'],host_config=client.create_host_config \
            # Need to adjust this for mac users - change /Users to /home

            (binds=[dataMap['osdp']['dockerhome'] + ':' + '/home',]))
            #(binds=['/home:/home',]))
            dockerpty.start(client, container_id)
Example #26
0
    def run_command(self, command):
        console.progress("> %s" % command)

        container = self.service.create_container(
            one_off=True,
            command=command,
            tty=False,
            stdin_open=True,
            detach=False)

        try:
            dockerpty.start(self.client, container.id, interactive=False)

            if container.wait() != 0:
                raise BuildFailedException()
                sys.exit(1)

        finally:
            self.client.remove_container(container.id, force=True)
Example #27
0
def run_one_off_container(container_options, project, service, options):
    if not options['--no-deps']:
        deps = service.get_linked_service_names()
        if deps:
            project.up(
                service_names=deps,
                start_deps=True,
                strategy=ConvergenceStrategy.never)

    project.initialize_networks()

    container = service.create_container(
        quiet=True,
        one_off=True,
        **container_options)

    if options['-d']:
        service.start_container(container)
        print(container.name)
        return

    def remove_container(force=False):
        if options['--rm']:
            project.client.remove_container(container.id, force=True)

    signals.set_signal_handler_to_shutdown()
    try:
        try:
            dockerpty.start(project.client, container.id, interactive=not options['-T'])
            service.connect_container_to_networks(container)
            exit_code = container.wait()
        except signals.ShutdownException:
            project.client.stop(container.id)
            exit_code = 1
    except signals.ShutdownException:
        project.client.kill(container.id)
        remove_container(force=True)
        sys.exit(2)

    remove_container()
    sys.exit(exit_code)
Example #28
0
def run():
    loader = PackageLoader()
    package = loader.load(os.getcwd())

    client_factory = DockerClientFactory()
    client = client_factory.get_client()

    container = client.create_container(
        image=package.current_image,
        stdin_open=True,
        tty=True,
        command="python {}".format(package.entry_point),
        working_dir=MOUNT_DIRECTORY,
        host_config=client.create_host_config(binds={
            os.getcwd(): {
                "bind": MOUNT_DIRECTORY,
                "mode": "rw"
            }
        })
    )

    dockerpty.start(client, container)
Example #29
0
    def run(self, step):
        """Execute the given step in docker."""
        cid = pu.sanitized_name(step.id, self._config.wid)

        container = self._find_container(cid)

        if not container and self._config.reuse:
            log.fail(
                f"Cannot find an existing container for step '{step.id}' to be reused"
            )

        if container and not self._config.reuse and not self._config.dry_run:
            container.remove(force=True)
            container = None

        if not container and not self._config.reuse:
            container = self._create_container(cid, step)

        log.info(f"[{step.id}] docker start")

        if self._config.dry_run:
            return 0

        self._spawned_containers.add(container)

        try:
            container.start()

            if self._config.pty:
                dockerpty.start(self._d.api, container.id)
            else:
                cout = container.logs(stream=True)
                for line in cout:
                    log.step_info(line.decode().rstrip())

            e = container.wait()["StatusCode"]
        except Exception as exc:
            log.fail(exc)
        return e
Example #30
0
 def __call__(self, *args, **kwargs):
     cli = self.swarm.client
     if cli is not None:
         rm_flag = kwargs.pop('rm')
         try:
             ret = cli.create_container(*args, **kwargs)
             if ret.get('Warnings') is not None:
                 print('[Warning] {message}'.format(message=ret['Warnings']))
             # try to start created container
             if ret.get('Id') is not None:
                 if kwargs['stdin_open'] and kwargs['tty']:
                     dockerpty.start(cli, ret['Id'])
                 else:
                     cli.start(ret['Id'])
                     # try to get the latest container
                     # check if container id is matched
                     # otherwise search containers since=self.container['Id']
                     latest_container = cli.containers(latest=True)[0]
                     if ret['Id'] == latest_container['Id']:
                         self._get_containers(latest=True)
                     else:
                         self._get_containers(since=ret['Id'], container_list=(ret['Id'],))
                     self._pretty_print()                     
                 if rm_flag:
                     cli.remove_container(ret['Id'])
         except errors.NotFound as e:
             print(e.explanation)
         except errors.APIError as e:
             print(e.explanation)
         except errors.DockerException as e:
             print(e.explanation)
         # volumes_from and dns arguments raise TypeError exception 
         # if they are used against v1.10 and above of the Docker remote API
         except TypeError as e:
             print(e)
         finally:
             cli.close()
def step_impl(ctx):
    pid, fd = pty.fork()

    if pid == pty.CHILD:
        tty = os.ttyname(0)
        sys.stdin = open(tty, 'r')
        sys.stdout = open(tty, 'w')
        sys.stderr = open(tty, 'w')

        try:
            dockerpty.start(ctx.client, ctx.container)
        except:
            os_.exit(1)

        os._exit(0)
    else:
        tty = os.ttyname(fd)
        ctx.pty = fd
        util.set_pty_size(
            ctx.pty,
            (ctx.rows, ctx.cols)
        )
        ctx.pid = pid
        util.wait(ctx.pty)
Example #32
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Allow insecure connections to the docker
                                  registry
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        insecure_registry = options['--allow-insecure-ssl']

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(service_names=deps,
                           start_deps=True,
                           recreate=False,
                           insecure_registry=insecure_registry,
                           detach=options['-d'])

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
            'detach': options['-d'],
        }

        if options['-e']:
            # Merge environment from config with -e command line
            container_options['environment'] = dict(
                parse_environment(service.options.get('environment')),
                **parse_environment(options['-e']))

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')

        if options['--user']:
            container_options['user'] = options.get('--user')

        if not options['--service-ports']:
            container_options['ports'] = []

        container = service.create_container(
            one_off=True,
            insecure_registry=insecure_registry,
            **container_options)

        if options['-d']:
            service.start_container(container)
            print(container.name)
        else:
            service.start_container(container)
            dockerpty.start(project.client,
                            container.id,
                            interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
 def open(self):
     lgr.debug("Opening TTY connection to docker container.")
     # TODO: probably call to super to assure that we have it running?
     dockerpty.start(self.client, self.container, logs=0)
Example #34
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Allow insecure connections to the docker
                                  registry
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        insecure_registry = options['--allow-insecure-ssl']

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_deps=True,
                    recreate=False,
                    insecure_registry=insecure_registry,
                    detach=options['-d']
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
            'detach': options['-d'],
        }

        if options['-e']:
            # Merge environment from config with -e command line
            container_options['environment'] = dict(
                parse_environment(service.options.get('environment')),
                **parse_environment(options['-e']))

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')

        if options['--rm']:
            container_options['restart'] = None

        if options['--user']:
            container_options['user'] = options.get('--user')

        if not options['--service-ports']:
            container_options['ports'] = []

        container = service.create_container(
            one_off=True,
            insecure_registry=insecure_registry,
            **container_options
        )

        if options['-d']:
            service.start_container(container)
            print(container.name)
        else:
            service.start_container(container)
            dockerpty.start(project.client, container.id, interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #35
0
    def _run_container(self, name, image_name, container_name
            , detach=False, command=None, tty=True, volumes=None, volumes_from=None, links=None, delete_on_exit=False, env=None, ports=None, dependency=False, no_intervention=False
            ):
        """Run a single container"""
        if not detach and dependency:
            tty = True
        log.info("Creating container from %s\timage=%s\tcontainer_name=%s\ttty=%s", image_name, name, container_name, tty)

        binds = {}
        volume_names = []
        if volumes is None:
            volumes = []

        uncreated = []
        for volume in volumes:
            if ":" in volume:
                name, bound = volume.split(":", 1)
                permissions = "rw"
                if ":" in bound:
                    bound, permissions = volume.split(":", 1)
                binds[name] = {"bind": bound, permissions: True}
                volume_names.append(bound)
                if not os.path.exists(name):
                    log.info("Making volume for mounting\tvolume=%s", name)
                    try:
                        os.makedirs(name)
                    except OSError as error:
                        uncreated.append((name, error))
        if uncreated:
            raise BadOption("Failed to create some volumes on the host", uncreated=uncreated)

        if volumes:
            log.info("\tUsing volumes\tvolumes=%s", volumes)
        if env:
            log.info("\tUsing environment\tenv=%s", env)
        if ports:
            log.info("\tUsing ports\tports=%s", ports.keys())
        container = self.docker_context.create_container(image_name
            , name=container_name
            , detach=detach
            , command=command
            , volumes=volumes
            , environment=env

            , tty = tty
            , ports = (ports or {}).keys()
            , stdin_open = tty
            )

        container_id = container
        if isinstance(container_id, dict):
            if "errorDetail" in container_id:
                raise BadImage("Failed to create container", image=name, error=container_id["errorDetail"])
            container_id = container_id["Id"]
        self._container_id = container_id
        self.already_running = True

        try:
            log.info("Starting container %s", container_name)
            if links:
                log.info("\tLinks: %s", links)
            if volumes_from:
                log.info("\tVolumes from: %s", volumes_from)
            if ports:
                log.info("\tPort Bindings: %s", ports)

            self.docker_context.start(container_id
                , links = links
                , binds = binds
                , volumes_from = volumes_from
                , port_bindings = ports
                )

            if not detach and not dependency:
                try:
                    dockerpty.start(self.docker_context, container_id)
                except KeyboardInterrupt:
                    pass

            inspection = None
            if not detach and not dependency:
                for _ in until(timeout=0.5, step=0.1, silent=True):
                    try:
                        inspection = self.docker_context.inspect_container(container_id)
                        if not isinstance(inspection, dict) or "State" not in inspection:
                            raise BadResult("Expected inspect result to be a dictionary with 'State' in it", found=inspection)
                        elif not inspection["State"]["Running"]:
                            break
                    except Exception as error:
                        log.error("Failed to see if container exited normally or not\thash=%s\terror=%s", container_id, error)

            if inspection and not no_intervention:
                if not inspection["State"]["Running"] and inspection["State"]["ExitCode"] != 0:
                    if self.interactive and not self.heira_formatted("harpoon.no_intervention", default=False):
                        print("!!!!")
                        print("Failed to run the container!")
                        print("Do you want commit the container in it's current state and /bin/bash into it to debug?")
                        answer = raw_input("[y]: ")
                        if not answer or answer.lower().startswith("y"):
                            with self.commit_and_run(container_id, command="/bin/bash"):
                                pass
                    raise BadImage("Failed to run container", container_id=container_id, container_name=container_name)
        finally:
            if delete_on_exit:
                self._stop_container(container_id, container_name)
Example #36
0
 def run_with_pty(self, interactive: bool = False) -> int:
     dockerpty.start(self._client.api, self._container.id, interactive=interactive, logs=True)
     exit_code = self.get_exit_code()
     self._container.remove()
     return exit_code
Example #37
0
    def execute(self):
        # prepare
        container_working_dir = self.cfg.env.container_working_dir
        working_dir = (
            pathlib.Path(self.cfg.global_config.working_dir).absolute().as_posix()
        )

        try:
            # linux/mac
            import dockerpty

            container = self.docker_cli.containers.create(
                name=self.cfg.env.name,
                image=self.cfg.env.image,
                command=self.cfg.env.entry_point,
                working_dir=container_working_dir,
                volumes={working_dir: {"bind": container_working_dir, "mode": "rw"}},
                auto_remove=True,
                # required
                tty=True,
                stdin_open=True,
            )
            dockerpty.start(self.docker_cli.api, container.id)
        except ImportError:
            # windows
            # i have no better idea now
            logout(
                "Your system does not support pty. Trying to use command line instead ..."
            )
            command = [
                "docker",
                "run",
                "-i",
                # remove after usage
                "--rm",
                # workspace
                "-v",
                f"{working_dir}:{container_working_dir}",
                "-w",
                container_working_dir,
                "--name",
                self.cfg.env.name,
                # image
                self.cfg.env.image,
                # interface
                self.cfg.env.entry_point,
            ]
            logout(f"start env: {command}")
            process = subprocess.Popen(command, stdin=subprocess.PIPE)

            try:
                while True:
                    user_input = input()
                    user_input += "\n"
                    process.stdin.write(user_input.encode())
                    process.stdin.flush()
            except KeyboardInterrupt:
                process.kill()
        finally:
            # end, stop it
            self.docker_cli.api.stop(self.cfg.env.name)
            logout("devcube end.")
Example #38
0
def run(docker, path, variables, yamls):
    """run a new container, using a predefined yaml"""
    allowed_paths = []
    if path is not None:
        for element in path.split(os.pathsep):
            allowed_paths.append(os.path.normcase(os.path.abspath(element)))

    for docker_file_name in yamls:

        # Check if the docker yaml file is in an allowed path
        if len(allowed_paths) > 0:
            # no path given, look in allowed path and use it as the file name
            # path is checked any way, to resolve symbolic links
            if os.path.basename(docker_file_name) == docker_file_name:
                for element in allowed_paths:
                    if os.path.exists(element + os.sep + docker_file_name):
                        # use that as the new file name
                        docker_file_name = element + os.sep + docker_file_name
                        break
            # Resolve to a absolute real path
            # symbolic links are resolve too
            real_file_name = os.path.normcase(os.path.realpath(docker_file_name))
            valid = False
            for element in allowed_paths:
                if os.path.commonprefix([element, real_file_name]) == element:
                    valid = True
            if not valid:
                print >> sys.stderr, "invalid yaml container: %s" % docker_file_name
                return 1

        # Load the yaml docker file
        with open(docker_file_name, 'r') as docker_file:
            try:
                docker_conf = yaml.safe_load(docker_file)
            except (yaml.scanner.ScannerError, yaml.parser.ParserError) as e:
                print >> sys.stderr,  e
                return 1


        # Match variables against the filters
        for (key, value) in docker_conf.pop('check', {}).items():
            if key not in variables:
                print >> sys.stderr,  "undefined variable '%s'" % key
                return 1
            #The variable check is a string, the filter is a regex
            if type(value) == str or type(value) == unicode:
                if re.match("^" + value + "$", variables[key]) is None:
                    print >> sys.stderr,  "variable %s not a valid value: '%s'" % (key, variables[key])
                    return 1
            # it's a list, search in allowed values
            elif type(value) == list:
                if not variables[key] in value:
                    print >> sys.stderr,  "variable %s not an allowed value" % key
                    return 1

        # resolve variables expression
        for (var, expression) in docker_conf.pop('variables', {}).items():
            try:
                variables[var] = eval(expression, {}, variables)
            except Exception as e:
                print >> sys.stderr, "evaluation failed for %s:" % (expression)
                for l in traceback.format_exception_only(type(e), e):
                    print "    " + l,
                    return 1

        docker_kwargs = TemplateDict(variables, docker_conf)

        effective_create_kwargs = {}
        effective_start_kwargs = {}
        effective_hostconfig_kwargs = {}

        # Converted the binding, must be given as an array of single-element hash
        # transformed to OrderedDict, docker-py expect a dict
        if 'binds' in docker_kwargs:
            binds = docker_kwargs['binds']
            if not isinstance(binds, list):
                print >> sys.stderr,  "binding must be an array"
                return 1
            new_binds = collections.OrderedDict()
            for bind in binds:
                (key, value) = bind.items()[0]
                # now inverse the source and destination
                # the docker api is incoherent between port bind and mount bind
                source_binding = value.pop('bind', key)
                value['bind'] = key
                new_binds[source_binding] = value
            docker_kwargs['binds'] = new_binds

        # if a script is given, save it as a temporary file
        if 'script' in docker_kwargs:
            script = docker_kwargs.pop('script')
            with tempfile.NamedTemporaryFile(delete=False) as script_file:
                script_file.write(script)
                script_file.flush()
                os.chmod(script_file.name,
                         (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) & ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH)
                docker_kwargs['command'] = [script_file.name]
            if 'binds' not in docker_kwargs:
                docker_kwargs['binds'] = collections.OrderedDict()
            docker_kwargs['binds'][script_file.name] = {'bind': script_file.name, 'ro': True}

        do_attach = not docker_kwargs.pop('detach', False)
        docker_kwargs['tty'] = do_attach
        docker_kwargs['stdin_open'] = do_attach

        do_rm = docker_kwargs.pop('rm', False)

        # list of capability to drop or add
        if 'cap_drop' in docker_kwargs and isinstance(docker_kwargs['cap_drop'], list):
            effective_start_kwargs['cap_drop'] = docker_kwargs.pop('cap_drop')
        if 'cap_add' in docker_kwargs and isinstance(docker_kwargs['cap_drop'], list):
            effective_start_kwargs['cap_add'] = docker_kwargs.pop('cap_add')

        # some exceptions, given in create_container, should be used in start:
        if 'volumes_from' in docker_kwargs:
            effective_hostconfig_kwargs['volumes_from'] = docker_kwargs.pop('volumes_from')
        if 'dns' in docker_kwargs:
            effective_hostconfig_kwargs['dns'] = docker_kwargs.pop('dns')

        # needs to manage port binding
        # it's dict of mapping
        # valid values for key is d+((-d+)|,d+)?(|tcp|udp)
        # valid values for destination is None, port, or a array of [host, port]
        # If a range was given, auto-increment destination
        if 'port_bindings' in docker_kwargs:
            effective_create_kwargs['ports'] = []
            port_bindings = {}
            for (port, port_definition) in docker_kwargs.pop('port_bindings').items():
                # If nothing, just a direct mapping
                if port_definition is None:
                    proto = "tcp"
                    listen_host = None
                    listen_ports = (port, )
                # if a plain integer, a one to one mapping
                elif type(port_definition) == int:
                    proto = "tcp"
                    listen_host = None
                    listen_ports = (port_definition, )
                else:
                    proto = port_definition.pop('protocol', 'tcp')
                    listen_host = port_definition.pop('host', None)
                    listen_range = port_definition.pop('range', None)
                    listen_ports = port_definition.pop('port', None)
                    if listen_ports is None and range is None:
                        listen_ports = (port, )
                    elif listen_ports is not None and listen_range is not None:
                        print >> sys.stderr, "port mapping %d given both range and port" % port
                        return 1
                    elif listen_ports is not None:
                        listen_ports = (listen_ports, )
                    elif listen_range is not None:
                        # we got a range
                        # it's  start,count
                        if listen_range.rfind(",") > 0:
                            listen_range = listen_range.split(",")
                            listen_ports = range(int(listen_range[0]), int(listen_range[0]) + int(listen_range[1]))
                        # or it start-stop
                        elif listen_range.rfind("-") > 0:
                            listen_range = listen_range.split("-")
                            listen_ports = range(int(listen_range[0]), int(listen_range[1]) + 1)
                    else:
                        print >> sys.stderr, "port mapping %d given neither range and port" % port
                        return 1
                for listen_port in listen_ports:
                    effective_create_kwargs['ports'].append((port, proto))
                    port_bindings["%d/%s" %(port, proto)] = (listen_host, listen_port)
                    port += 1

            effective_hostconfig_kwargs['port_bindings'] = port_bindings

        # Extract argument for hostconfig
        for arg_name in inspect.getargspec(dockerlib.utils.create_host_config).args:
            if arg_name in docker_kwargs:
                effective_hostconfig_kwargs[arg_name] = docker_kwargs.pop(arg_name)
        effective_create_kwargs['host_config'] = dockerlib.utils.create_host_config(**effective_hostconfig_kwargs)

        #start with 1, 0 is 'self'
        for arg_name in inspect.getargspec(dockerlib.Client.create_container).args[1:]:
            if arg_name in docker_kwargs:
                effective_create_kwargs[arg_name] = docker_kwargs.pop(arg_name)
        #start with 1, 0 is 'self'
        for arg_name in inspect.getargspec(dockerlib.Client.start).args[1:]:
            if arg_name in docker_kwargs:
                effective_start_kwargs[arg_name] = docker_kwargs.pop(arg_name)

        # don' forget to store the container creator
        if not 'environment' in effective_create_kwargs:
            effective_create_kwargs['environment'] = {}
        effective_create_kwargs['environment']['CONTAINER_CREATOR'] = variables['environment.SUDO_USER']

        # is a numeric id given for the user, or is it needed to resolve it ?
        if 'user' in effective_create_kwargs and not isinstance(effective_create_kwargs['user'], (int, long)):
            user = effective_create_kwargs['user']
            try:
                effective_create_kwargs['user'] = getpwnam(user).pw_uid
            except KeyError:
                print >> sys.stderr, "user '%s' not found" % user
                return 1

        if len(docker_kwargs) > 0:
            print >> sys.stderr, "invalid argument: %s" % docker_kwargs
            return 1

        container = docker.create_container(**effective_create_kwargs)
        if container['Warnings'] is not None:
            print >> sys.stderr, "warning: %s" % container.Warnings

        if do_attach:
            try:
                dockerpty.start(docker, container, **effective_start_kwargs)
                if do_rm:
                    docker.remove_container(container, v=True)
            except dockerlib.errors.APIError as e:
                print >> sys.stderr, e
            except socket.error:
                print >> sys.stderr, "container detached"
        else:
            docker.start(container, **effective_start_kwargs)

    return 0
Example #39
0
 def handler():
     dockerpty.start(self.host.client, container_pointer)
     self.host.client.remove_container(container_pointer)
Example #40
0
#!/usr/bin/env python

import dockerpty
import os
from docker.client import Client
from docker.utils import kwargs_from_env

client = Client(base_url=os.environ['DOCKER_HOST'], version=os.environ['DOCKER_SERVER_API_VERSION'])
container = client.create_container(image="debian:wheezy", stdin_open=True, tty=True, command='echo "passed"')
dockerpty.start(client, container)
Example #41
0
def execute_tests_in_container(
    distro_name: str,
    docker_tag: str,
    version: CMKVersion,
    result_path: Path,
    command: List[str],
    interactive: bool,
) -> int:
    client = _docker_client()
    info = client.info()
    logger.info("Docker version: %s", info["ServerVersion"])

    base_image_name = "%s/%s" % (_DOCKER_REGISTRY, distro_name)
    image_name_with_tag = _create_cmk_image(client, base_image_name,
                                            docker_tag, version)

    # Start the container
    with _start(
            client,
            image=image_name_with_tag,
            command="/bin/bash",
            volumes=list(_runtime_volumes().keys()),
            host_config=client.api.create_host_config(
                # Create some init process that manages signals and processes
                init=True,
                # needed to make the overlay mounts work on the /git directory
                # Should work, but does not seem to be enough: 'cap_add=["SYS_ADMIN"]'. Using this instead:
                privileged=True,
                # Important to workaround really high default of docker which results
                # in problems when trying to close all FDs in Python 2.
                ulimits=[
                    docker.types.Ulimit(name="nofile", soft=2048, hard=2048),
                ],
                binds=[
                    ":".join([k, v["bind"], v["mode"]])
                    for k, v in _runtime_volumes().items()
                ],
                # Our SNMP integration tests need SNMP. For this reason we enable the IPv6 support
                # docker daemon wide, but set some fixed local network which is not being routed.
                # This makes it possible to use IPv6 on the "lo" interface. Externally IPv4 is used
                sysctls={
                    "net.ipv6.conf.eth0.disable_ipv6": 1,
                },
            ),
            stdin_open=True,
            tty=True,
    ) as container:
        # Ensure we can make changes to the git directory (not persisting it outside of the container)
        _prepare_git_overlay(container, "/git-lowerdir", "/git")
        _cleanup_previous_virtual_environment(container, version)
        _reuse_persisted_virtual_environment(container, version)

        if interactive:
            logger.info("+-------------------------------------------------")
            logger.info("| Next steps:")
            logger.info("| ")
            logger.info("| /git/scripts/run-pipenv shell")
            logger.info("| cd /git")
            logger.info("| ")
            logger.info("| ... start whatever test you want, for example:")
            logger.info("| ")
            logger.info("| make -C tests test-integration")
            logger.info("| ")
            logger.info("|   Execute all integration tests")
            logger.info("| ")
            logger.info("| tests/scripts/run-integration-test.py "
                        "tests/integration/livestatus/test_livestatus.py")
            logger.info("| ")
            logger.info("|   Execute some integration tests")
            logger.info("| ")
            logger.info("| tests/scripts/run-integration-test.py "
                        "tests/integration/livestatus/test_livestatus.py "
                        "-k test_service_custom_variables ")
            logger.info("| ")
            logger.info("|   Execute a single test")
            logger.info("| ")
            logger.info("+-------------------------------------------------")
            dockerpty.start(client.api, container.id)
            return 0

        # Now execute the real test in the container context
        exit_code = _exec_run(
            container,
            command,
            environment=_container_env(version),
            workdir="/git",
            stream=True,
        )

        # Collect the test results located in /results of the container. The
        # jenkins job will make it available as artifact later
        _copy_directory(container, Path("/results"), result_path)

        return exit_code
Example #42
0
def run(docker, path, variables, yamls):
    """run a new container, using a predefined yaml"""
    allowed_paths = []
    if path is not None:
        for element in path.split(os.pathsep):
            allowed_paths.append(os.path.normcase(os.path.abspath(element)))

    for docker_file_name in yamls:

        # Check if the docker yaml file is in an allowed path
        if len(allowed_paths) > 0:
            # no path given, look in allowed path and use it as the file name
            # path is checked any way, to resolve symbolic links
            if os.path.basename(docker_file_name) == docker_file_name:
                for element in allowed_paths:
                    if os.path.exists(element + os.sep + docker_file_name):
                        # use that as the new file name
                        docker_file_name = element + os.sep + docker_file_name
                        break
            # Resolve to a absolute real path
            # symbolic links are resolve too
            real_file_name = os.path.normcase(
                os.path.realpath(docker_file_name))
            valid = False
            for element in allowed_paths:
                if os.path.commonprefix([element, real_file_name]) == element:
                    valid = True
            if not valid:
                print >> sys.stderr, "invalid yaml container: %s" % docker_file_name
                return 1

        # Load the yaml docker file
        with open(docker_file_name, 'r') as docker_file:
            try:
                docker_conf = yaml.safe_load(docker_file)
            except (yaml.scanner.ScannerError, yaml.parser.ParserError) as e:
                print >> sys.stderr, e
                return 1

        # Match variables against the filters
        for (key, value) in docker_conf.pop('check', {}).items():
            if key not in variables:
                print >> sys.stderr, "undefined variable '%s'" % key
                return 1
            #The variable check is a string, the filter is a regex
            if type(value) == str or type(value) == unicode:
                if re.match("^" + value + "$", variables[key]) is None:
                    print >> sys.stderr, "variable %s not a valid value: '%s'" % (
                        key, variables[key])
                    return 1
            # it's a list, search in allowed values
            elif type(value) == list:
                if not variables[key] in value:
                    print >> sys.stderr, "variable %s not an allowed value" % key
                    return 1

        # resolve variables expression
        for (var, expression) in docker_conf.pop('variables', {}).items():
            try:
                variables[var] = eval(expression, {}, variables)
            except Exception as e:
                print >> sys.stderr, "evaluation failed for %s:" % (expression)
                for l in traceback.format_exception_only(type(e), e):
                    print "    " + l,
                    return 1

        docker_kwargs = TemplateDict(variables, docker_conf)

        effective_create_kwargs = {}
        effective_start_kwargs = {}
        effective_hostconfig_kwargs = {}

        # Converted the binding, must be given as an array of single-element hash
        # transformed to OrderedDict, docker-py expect a dict
        if 'binds' in docker_kwargs:
            binds = docker_kwargs['binds']
            if not isinstance(binds, list):
                print >> sys.stderr, "binding must be an array"
                return 1
            new_binds = collections.OrderedDict()
            for bind in binds:
                (key, value) = bind.items()[0]
                # now inverse the source and destination
                # the docker api is incoherent between port bind and mount bind
                source_binding = value.pop('bind', key)
                value['bind'] = key
                new_binds[source_binding] = value
            docker_kwargs['binds'] = new_binds

        # if a script is given, save it as a temporary file
        if 'script' in docker_kwargs:
            script = docker_kwargs.pop('script')
            with tempfile.NamedTemporaryFile(delete=False) as script_file:
                script_file.write(script)
                script_file.flush()
                os.chmod(script_file.name,
                         (stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
                         & ~stat.S_IWUSR & ~stat.S_IWGRP & ~stat.S_IWOTH)
                docker_kwargs['command'] = [script_file.name]
            if 'binds' not in docker_kwargs:
                docker_kwargs['binds'] = collections.OrderedDict()
            docker_kwargs['binds'][script_file.name] = {
                'bind': script_file.name,
                'ro': True
            }

        do_attach = not docker_kwargs.pop('detach', False)
        docker_kwargs['tty'] = do_attach
        docker_kwargs['stdin_open'] = do_attach

        do_rm = docker_kwargs.pop('rm', False)

        # list of capability to drop or add
        if 'cap_drop' in docker_kwargs and isinstance(
                docker_kwargs['cap_drop'], list):
            effective_start_kwargs['cap_drop'] = docker_kwargs.pop('cap_drop')
        if 'cap_add' in docker_kwargs and isinstance(docker_kwargs['cap_drop'],
                                                     list):
            effective_start_kwargs['cap_add'] = docker_kwargs.pop('cap_add')

        # some exceptions, given in create_container, should be used in start:
        if 'volumes_from' in docker_kwargs:
            effective_hostconfig_kwargs['volumes_from'] = docker_kwargs.pop(
                'volumes_from')
        if 'dns' in docker_kwargs:
            effective_hostconfig_kwargs['dns'] = docker_kwargs.pop('dns')

        # needs to manage port binding
        # it's dict of mapping
        # valid values for key is d+((-d+)|,d+)?(|tcp|udp)
        # valid values for destination is None, port, or a array of [host, port]
        # If a range was given, auto-increment destination
        if 'port_bindings' in docker_kwargs:
            effective_create_kwargs['ports'] = []
            port_bindings = {}
            for (port, port_definition
                 ) in docker_kwargs.pop('port_bindings').items():
                # If nothing, just a direct mapping
                if port_definition is None:
                    proto = "tcp"
                    listen_host = None
                    listen_ports = (port, )
                # if a plain integer, a one to one mapping
                elif type(port_definition) == int:
                    proto = "tcp"
                    listen_host = None
                    listen_ports = (port_definition, )
                else:
                    proto = port_definition.pop('protocol', 'tcp')
                    listen_host = port_definition.pop('host', None)
                    listen_range = port_definition.pop('range', None)
                    listen_ports = port_definition.pop('port', None)
                    if listen_ports is None and range is None:
                        listen_ports = (port, )
                    elif listen_ports is not None and listen_range is not None:
                        print >> sys.stderr, "port mapping %d given both range and port" % port
                        return 1
                    elif listen_ports is not None:
                        listen_ports = (listen_ports, )
                    elif listen_range is not None:
                        # we got a range
                        # it's  start,count
                        if listen_range.rfind(",") > 0:
                            listen_range = listen_range.split(",")
                            listen_ports = range(
                                int(listen_range[0]),
                                int(listen_range[0]) + int(listen_range[1]))
                        # or it start-stop
                        elif listen_range.rfind("-") > 0:
                            listen_range = listen_range.split("-")
                            listen_ports = range(int(listen_range[0]),
                                                 int(listen_range[1]) + 1)
                    else:
                        print >> sys.stderr, "port mapping %d given neither range and port" % port
                        return 1
                for listen_port in listen_ports:
                    effective_create_kwargs['ports'].append((port, proto))
                    port_bindings["%d/%s" % (port, proto)] = (listen_host,
                                                              listen_port)
                    port += 1

            effective_hostconfig_kwargs['port_bindings'] = port_bindings

        # Extract argument for hostconfig
        for arg_name in inspect.getargspec(
                dockerlib.utils.create_host_config).args:
            if arg_name in docker_kwargs:
                effective_hostconfig_kwargs[arg_name] = docker_kwargs.pop(
                    arg_name)
        effective_create_kwargs[
            'host_config'] = dockerlib.utils.create_host_config(
                **effective_hostconfig_kwargs)

        #start with 1, 0 is 'self'
        for arg_name in inspect.getargspec(
                dockerlib.Client.create_container).args[1:]:
            if arg_name in docker_kwargs:
                effective_create_kwargs[arg_name] = docker_kwargs.pop(arg_name)
        #start with 1, 0 is 'self'
        for arg_name in inspect.getargspec(dockerlib.Client.start).args[1:]:
            if arg_name in docker_kwargs:
                effective_start_kwargs[arg_name] = docker_kwargs.pop(arg_name)

        # don' forget to store the container creator
        if not 'environment' in effective_create_kwargs:
            effective_create_kwargs['environment'] = {}
        effective_create_kwargs['environment'][
            'CONTAINER_CREATOR'] = variables['environment.SUDO_USER']

        # is a numeric id given for the user, or is it needed to resolve it ?
        if 'user' in effective_create_kwargs and not isinstance(
                effective_create_kwargs['user'], (int, long)):
            user = effective_create_kwargs['user']
            try:
                effective_create_kwargs['user'] = getpwnam(user).pw_uid
            except KeyError:
                print >> sys.stderr, "user '%s' not found" % user
                return 1

        if len(docker_kwargs) > 0:
            print >> sys.stderr, "invalid argument: %s" % docker_kwargs
            return 1

        container = docker.create_container(**effective_create_kwargs)
        if container['Warnings'] is not None:
            print >> sys.stderr, "warning: %s" % container.Warnings

        if do_attach:
            try:
                dockerpty.start(docker, container, **effective_start_kwargs)
                if do_rm:
                    docker.remove_container(container, v=True)
            except dockerlib.errors.APIError as e:
                print >> sys.stderr, e
            except socket.error:
                print >> sys.stderr, "container detached"
        else:
            docker.start(container, **effective_start_kwargs)

    return 0
Example #43
0
import docker
import dockerpty

c = docker.Client(base_url='unix://var/run/docker.sock')
container_id = c.create_container(
  image='ubuntu:14.04',
  stdin_open=True,
  tty=True,
  command='/bin/bash'
)

dockerpty.start(c, container_id)
Example #44
0
    def run(self, options):
        """

        :param options:
        :return:
        """
        if options.entrypoint == "runtest":
            raise ValueError(
                "You cannot use the entrypoint 'runtest' in interactive mode!")
        try:

            # prepare the Docker image (updating it if required)
            docker_image = self.get_image_name(options, options.skip_update)

            # volumes
            vmounts, volumes = self._parse_volumes(options.volume)

            # ports
            ports = self._parse_ports(options.port)

            # environment
            environment = [
                "GALAXY_URL={0}".format(options.server),
                "GALAXY_API_KEY={0}".format(options.api_key)
            ]

            # command
            command = [
                options.entrypoint, "--server", options.server, "--api-key",
                options.api_key
            ]
            if "web_port" in options:
                command.extend(["--port", "{}".format(options.web_port)])
            import socket
            # create and run Docker containers
            client = _docker.APIClient()
            container = client.create_container(
                image=docker_image,
                stdin_open=True,
                tty=True,
                hostname=socket.gethostname(),
                command=command,
                environment=environment,
                volumes=vmounts,
                ports=list(ports.keys()),
                host_config=client.create_host_config(binds=volumes,
                                                      port_bindings=ports))
            _logger.info("Started Docker container %s", container["Id"])
            _dockerpty.start(client, container)
            client.remove_container(container["Id"])
            _logger.info("Removed Docker container %s", container["Id"])
            return _SUCCESS_EXIT
        except NameError as ne:
            if options and options.debug:
                _logger.exception(ne)
            print(
                "\n ERROR: To use wft4galaxy-docker in development mode "
                "you need to install 'docker' and 'dockerpty' Python libries \n"
                "\tType \"pip install docker dockerpty\" to install the required libraries.\n"
            )
            return _FAILURE_EXIT
        except Exception as e:
            _logger.error(
                "ERROR: Unable to start the Docker container: {0}".format(
                    str(e)))
            if options and options.debug:
                _logger.exception(e)
            return _FAILURE_EXIT
Example #45
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Deprecated - no effect.
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --name NAME           Assign a name to the container
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            -p, --publish=[]      Publish a container's port(s) to the host
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        if options['--allow-insecure-ssl']:
            log.warn(INSECURE_SSL_WARNING)

        if not options['--no-deps']:
            deps = service.get_linked_service_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_deps=True,
                    strategy=ConvergenceStrategy.never,
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
            'detach': options['-d'],
        }

        if options['-e']:
            container_options['environment'] = parse_environment(options['-e'])

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')

        if options['--rm']:
            container_options['restart'] = None

        if options['--user']:
            container_options['user'] = options.get('--user')

        if not options['--service-ports']:
            container_options['ports'] = []

        if options['--publish']:
            container_options['ports'] = options.get('--publish')

        if options['--publish'] and options['--service-ports']:
            raise UserError(
                'Service port mapping and manual port mapping '
                'can not be used togather'
            )

        if options['--name']:
            container_options['name'] = options['--name']

        try:
            container = service.create_container(
                quiet=True,
                one_off=True,
                **container_options
            )
        except APIError as e:
            legacy.check_for_legacy_containers(
                project.client,
                project.name,
                [service.name],
                allow_one_off=False,
            )

            raise e

        if options['-d']:
            service.start_container(container)
            print(container.name)
        else:
            dockerpty.start(project.client, container.id, interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #46
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Allow insecure connections to the docker
                                  registry
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options["SERVICE"])

        insecure_registry = options["--allow-insecure-ssl"]

        if not options["--no-deps"]:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps, start_deps=True, allow_recreate=False, insecure_registry=insecure_registry
                )

        tty = True
        if options["-d"] or options["-T"] or not sys.stdin.isatty():
            tty = False

        if options["COMMAND"]:
            command = [options["COMMAND"]] + options["ARGS"]
        else:
            command = service.options.get("command")

        container_options = {"command": command, "tty": tty, "stdin_open": not options["-d"], "detach": options["-d"]}

        if options["-e"]:
            container_options["environment"] = parse_environment(options["-e"])

        if options["--entrypoint"]:
            container_options["entrypoint"] = options.get("--entrypoint")

        if options["--rm"]:
            container_options["restart"] = None

        if options["--user"]:
            container_options["user"] = options.get("--user")

        if not options["--service-ports"]:
            container_options["ports"] = []

        try:
            container = service.create_container(
                quiet=True, one_off=True, insecure_registry=insecure_registry, **container_options
            )
        except APIError as e:
            legacy.check_for_legacy_containers(project.client, project.name, [service.name], allow_one_off=False)

            raise e

        if options["-d"]:
            service.start_container(container)
            print(container.name)
        else:
            dockerpty.start(project.client, container.id, interactive=not options["-T"])
            exit_code = container.wait()
            if options["--rm"]:
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #47
0
File: main.py Project: leishman/fig
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ fig run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `fig run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Allow insecure connections to the docker
                                  registry
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            -T                    Disable pseudo-tty allocation. By default `fig run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        insecure_registry = options['--allow-insecure-ssl']

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_links=True,
                    recreate=False,
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
        }

        if options['-e']:
            for option in options['-e']:
                if 'environment' not in service.options:
                    service.options['environment'] = {}
                k, v = option.split('=', 1)
                service.options['environment'][k] = v

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')
        container = service.create_container(
            one_off=True,
            insecure_registry=insecure_registry,
            **container_options)
        if options['-d']:
            service.start_container(container, ports=None, one_off=True)
            print(container.name)
        else:
            service.start_container(container, ports=None, one_off=True)
            dockerpty.start(project.client,
                            container.id,
                            interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #48
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Deprecated - no effect.
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --name NAME           Assign a name to the container
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            -p, --publish=[]      Publish a container's port(s) to the host
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options["SERVICE"])

        detach = options["-d"]

        if IS_WINDOWS_PLATFORM and not detach:
            raise UserError(
                "Interactive mode is not yet supported on Windows.\n"
                "Please pass the -d flag when using `docker-compose run`."
            )

        if options["--allow-insecure-ssl"]:
            log.warn(INSECURE_SSL_WARNING)

        if not options["--no-deps"]:
            deps = service.get_linked_service_names()

            if len(deps) > 0:
                project.up(service_names=deps, start_deps=True, strategy=ConvergenceStrategy.never)
            elif project.use_networking:
                project.ensure_network_exists()

        tty = True
        if detach or options["-T"] or not sys.stdin.isatty():
            tty = False

        if options["COMMAND"]:
            command = [options["COMMAND"]] + options["ARGS"]
        else:
            command = service.options.get("command")

        container_options = {"command": command, "tty": tty, "stdin_open": not detach, "detach": detach}

        if options["-e"]:
            container_options["environment"] = parse_environment(options["-e"])

        if options["--entrypoint"]:
            container_options["entrypoint"] = options.get("--entrypoint")

        if options["--rm"]:
            container_options["restart"] = None

        if options["--user"]:
            container_options["user"] = options.get("--user")

        if not options["--service-ports"]:
            container_options["ports"] = []

        if options["--publish"]:
            container_options["ports"] = options.get("--publish")

        if options["--publish"] and options["--service-ports"]:
            raise UserError("Service port mapping and manual port mapping " "can not be used togather")

        if options["--name"]:
            container_options["name"] = options["--name"]

        try:
            container = service.create_container(quiet=True, one_off=True, **container_options)
        except APIError as e:
            legacy.check_for_legacy_containers(project.client, project.name, [service.name], allow_one_off=False)

            raise e

        if detach:
            service.start_container(container)
            print(container.name)
        else:
            dockerpty.start(project.client, container.id, interactive=not options["-T"])
            exit_code = container.wait()
            if options["--rm"]:
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #49
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ docker-compose run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `docker-compose run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-p PORT...] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Deprecated - no effect.
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --name NAME           Assign a name to the container
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            -u, --user=""         Run as specified username or uid
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            -p, --publish=[]      Publish a container's port(s) to the host
            --service-ports       Run command with the service's ports enabled and mapped
                                  to the host.
            -T                    Disable pseudo-tty allocation. By default `docker-compose run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        detach = options['-d']

        if IS_WINDOWS_PLATFORM and not detach:
            raise UserError(
                "Interactive mode is not yet supported on Windows.\n"
                "Please pass the -d flag when using `docker-compose run`.")

        if options['--allow-insecure-ssl']:
            log.warn(INSECURE_SSL_WARNING)

        if not options['--no-deps']:
            deps = service.get_linked_service_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_deps=True,
                    strategy=ConvergenceStrategy.never,
                )

        tty = True
        if detach or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not detach,
            'detach': detach,
        }

        if options['-e']:
            container_options['environment'] = parse_environment(options['-e'])

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')

        if options['--rm']:
            container_options['restart'] = None

        if options['--user']:
            container_options['user'] = options.get('--user')

        if not options['--service-ports']:
            container_options['ports'] = []

        if options['--publish']:
            container_options['ports'] = options.get('--publish')

        if options['--publish'] and options['--service-ports']:
            raise UserError('Service port mapping and manual port mapping '
                            'can not be used togather')

        if options['--name']:
            container_options['name'] = options['--name']

        try:
            container = service.create_container(quiet=True,
                                                 one_off=True,
                                                 **container_options)
        except APIError as e:
            legacy.check_for_legacy_containers(
                project.client,
                project.name,
                [service.name],
                allow_one_off=False,
            )

            raise e

        if detach:
            service.start_container(container)
            print(container.name)
        else:
            dockerpty.start(project.client,
                            container.id,
                            interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #50
0
    def run(self, project, options):
        """
        Run a one-off command on a service.

        For example:

            $ fig run web python manage.py shell

        By default, linked services will be started, unless they are already
        running. If you do not want to start linked services, use
        `fig run --no-deps SERVICE COMMAND [ARGS...]`.

        Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]

        Options:
            --allow-insecure-ssl  Allow insecure connections to the docker
                                  registry
            -d                    Detached mode: Run container in the background, print
                                  new container name.
            --entrypoint CMD      Override the entrypoint of the image.
            -e KEY=VAL            Set an environment variable (can be used multiple times)
            --no-deps             Don't start linked services.
            --rm                  Remove container after run. Ignored in detached mode.
            -T                    Disable pseudo-tty allocation. By default `fig run`
                                  allocates a TTY.
        """
        service = project.get_service(options['SERVICE'])

        insecure_registry = options['--allow-insecure-ssl']

        if not options['--no-deps']:
            deps = service.get_linked_names()

            if len(deps) > 0:
                project.up(
                    service_names=deps,
                    start_links=True,
                    recreate=False,
                    insecure_registry=insecure_registry,
                )

        tty = True
        if options['-d'] or options['-T'] or not sys.stdin.isatty():
            tty = False

        if options['COMMAND']:
            command = [options['COMMAND']] + options['ARGS']
        else:
            command = service.options.get('command')

        container_options = {
            'command': command,
            'tty': tty,
            'stdin_open': not options['-d'],
        }

        if options['-e']:
            for option in options['-e']:
                if 'environment' not in service.options:
                    service.options['environment'] = {}
                k, v = option.split('=', 1)
                service.options['environment'][k] = v

        if options['--entrypoint']:
            container_options['entrypoint'] = options.get('--entrypoint')
        container = service.create_container(
            one_off=True,
            insecure_registry=insecure_registry,
            **container_options
        )
        if options['-d']:
            service.start_container(container, ports=None, one_off=True)
            print(container.name)
        else:
            service.start_container(container, ports=None, one_off=True)
            dockerpty.start(project.client, container.id, interactive=not options['-T'])
            exit_code = container.wait()
            if options['--rm']:
                log.info("Removing %s..." % container.name)
                project.client.remove_container(container.id)
            sys.exit(exit_code)
Example #51
0
    def runContainer(self, client):
        self.container_config = self.config.getContainerConfig()
        container_args = {}
        container_config = {}
        host_config = {}
        network_config = {}

        if self.container_config.get("command") is not None:
            if isinstance(self.container_config["command"], list):
                container_args["command"] = [
                    "bash", "-c", "${HOME}/pre_run.sh && exec",
                    " ".join(self.container_config["command"])
                ]
            else:
                container_args["command"] = [
                    "bash", "-c", "${HOME}/pre_run.sh && exec",
                    self.container_config["command"]
                ]

        if self.container_config.get("entrypoint") is not None:
            container_args["entrypoint"] = self.container_config.get(
                "entrypoint")

        if self.container_config.get("workingDir") is not None:
            container_args["working_dir"] = self.container_config.get(
                "workingDir")

        if self.container_config.get("shm_size") is not None:
            host_config["shm_size"] = self.container_config.get("shm_size")

        if self.container_config.get("seccomp_profile") is not None:
            # This expects a file
            if (self.config.get("seccomp_dir")):
                if os.path.exists(
                        os.path.join(
                            self.config.get("seccomp_dir"),
                            self.container_config.get("seccomp_profile"))):
                    seccomp = open(
                        os.path.join(
                            self.config.get("seccomp_dir"),
                            self.container_config.get("seccomp_profile")))
                    host_config["security_opt"] = [
                        "seccomp=" + " ".join(seccomp.read().splitlines())
                    ]
            elif os.path.exists(self.container_config.get("seccomp_profile")):
                seccomp = open(self.container_config.get("seccomp_profile"))
                host_config["security_opt"] = [
                    "seccomp=" + " ".join(seccomp.read().splitlines())
                ]
            else:
                # Bail since we don't want to run a container that expects a security profile but can't find one!
                print("Seccomp profile not found: %s / %s - Aborting!" %
                      (self.config.get("seccomp_dir"),
                       self.container_config.get("seccomp_profile")))
                sys.exit(1)

        container_args["image"] = self.container_config[
            "image"] + ":" + self.container_config.get("tag", "latest")
        container_args["ports"] = [
            key for key in self.container_config.get("ports") or []
        ]
        container_args["detach"] = False

        if self.container_config.get("tty") == True:
            container_args["tty"] = True

        if self.container_config.get("workdir"):
            container_args["working_dir"] = self.container_config.get(
                "workdir")

        if self.container_config.get("stdin_open") == True:
            container_args["stdin_open"] = True

        # This requires docker-py as per PR #2465 from Ryan Leary
        # This also allows Vulkan to run in a user namespace, otherwise X tends to crash.

        if self.container_config.get("gpu_hook") is not None:
            if self.container_config["gpu_hook"].get("enabled") is True:
                host_config["device_requests"] = [
                    docker.types.DeviceRequest(count=-1,
                                               capabilities=[['gpu']])
                ]

        print("self.container_config[environment] is %s" %
              self.container_config["environment"])
        print("self.environment is %s" % self.environment)

        container_args["environment"] = {
            **self.container_config["environment"],
            **self.environment
        }

        if container_args.get("name") is not None:
            container_args["name"] = self.container_config["name"]
        elif self.container_config.get("name"):
            container_args["name"] = self.container_config.get("name")
        elif self.config.get("subprofileUser"):
            container_args["name"] = self.container_config["image"].replace(
                '/', '-') + "-" + self.config.safe_get("subprofileUser")
        else:
            container_args["name"] = self.container_config["image"].replace(
                '/', '-') + "-" + self.config.safe_get("profileUser")

        container_args["hostname"] = container_args["name"]
        host_config["auto_remove"] = True
        host_config["port_bindings"] = self.container_config.get("ports")
        host_config["binds"] = self.mounts
        host_config["devices"] = self.devices

        networking_config = {}

        if self.config.get("container", "network_mode") == "host":
            host_config["network_mode"] = "host"
        elif self.config.get("container", "network_mode") == "none":
            host_config["network_mode"] = "none"
        else:
            if self.config.get("container",
                               "network") is not None and self.config.get(
                                   "devices", "network", "enabled") is True:
                networking_config = client.create_networking_config({
                    self.config.get("container", "network", "name"):
                    client.create_endpoint_config()
                })

        print("Container args is %s" % container_args)
        print("Building container")

        # This is gross, FIXME
        if networking_config:
            container = client.create_container(
                **container_args,
                host_config=client.create_host_config(**host_config),
                networking_config=networking_config)
        else:
            container = client.create_container(
                **container_args,
                host_config=client.create_host_config(**host_config))

        # if self.config.get("container", "network") is not None and self.config.get("devices", "network", "enabled") is True:
        #     network_config["net_id"] = self.config.get("container", "network", "name")
        #     client.connect_container_to_network(container=container.get('Id'), **network_config)

        self.injectConfigs(client, container)
        print("Running container with entrypoint %s: " %
              container_args["entrypoint"])
        client.start(container=container.get('Id'))

        # Check for the process
        if self.config.getAppConfig().get(
                "running_executable"
        ) is not None and not self.container_config.get("stdin_open"):

            while (True):
                print("Waiting on the process %s to run post_run script..." %
                      self.config.getAppConfig().get("running_executable"))
                try:
                    subprocess.check_output([
                        "pgrep",
                        self.config.getAppConfig().get("running_executable")
                    ])
                    print("Found process, running script.")
                    break
                except Exception as e:
                    print("Still waiting... %s" % e)
                    time.sleep(5)
                    continue

            print("Running post_run script")
            post_run_exec = client.exec_create(
                container=container.get('Id'),
                cmd=["/bin/bash", "-c", "${HOME}/post_run.sh"])
            exec_start = client.exec_start(exec_id=post_run_exec, stream=True)

            for msg in exec_start:
                print(msg)

        if container_args.get("stdin_open"):
            print("Entering interactive mode.")
            dockerpty.start(client, container=container.get('Id'))

        client.wait(container=container.get('Id'))