Ejemplo n.º 1
0
    def scale(self, options):
        """
        Set number of containers to run for a service.

        Numbers are specified in the form `service=num` as arguments.
        For example:

            $ docker-compose scale web=2 worker=3

        Usage: scale [options] [SERVICE=NUM...]

        Options:
          -t, --timeout TIMEOUT      Specify a shutdown timeout in seconds.
                                     (default: 10)
        """
        timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)

        for s in options['SERVICE=NUM']:
            if '=' not in s:
                raise UserError(
                    'Arguments to scale should be in the form service=num')
            service_name, num = s.split('=', 1)
            try:
                num = int(num)
            except ValueError:
                raise UserError(
                    'Number of containers for service "%s" is not a '
                    'number' % service_name)
            self.project.get_service(service_name).scale(num, timeout=timeout)
Ejemplo n.º 2
0
    def run(self, 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:
            -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.
            -w, --workdir=""      Working directory inside the container
        """
        service = self.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['--publish'] and options['--service-ports']:
            raise UserError('Service port mapping and manual port mapping '
                            'can not be used togather')

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

        container_options = build_container_options(options, detach, command)
        exit_code = run_one_off_container(container_options, self.project,
                                          service, options)
        output['code'] = exit_code
        return output
Ejemplo n.º 3
0
def voodoo_load_yaml(file_name):
    try:
        # Load default voodoo config
        default_config_path = os.path.join(os.path.expanduser("~"), '.voodoo',
                                           'config.yml')
        with open(default_config_path, 'r') as fh:
            voodoo_config = yaml.safe_load(fh)

        with open(file_name, 'r') as fh:
            #Load custom config
            config = yaml.safe_load(fh)

            #update voodoo config
            voodoo_config.update(config.pop('voodoo', {}))

            # share .voodoo folder in voodoo
            home = os.path.expanduser("~")
            shared = os.path.join(home, '.voodoo', 'shared')
            config['odoo']['volumes'].append('%s:%s' % (shared, shared))

            # Add gitconfig in voodoo
            if 'gitconfig' in voodoo_config:
                gitconfig = os.path.expanduser(voodoo_config['gitconfig'])
                config['odoo']['volumes'].append(
                    '%s:/home/devstep/.gitconfig' % (gitconfig))

            #Add environment variable
            config['odoo']['environment'] += [
                'SHARED_FOLDER=%s' % shared,
                'SHARED_EGGS=%s' % str(voodoo_config['shared_eggs']).lower(),
            ]
            return config
    except IOError as e:
        raise UserError(six.text_type(e))
Ejemplo n.º 4
0
def image_type_from_opt(flag, value):
    if not value:
        return ImageType.none
    try:
        return ImageType[value]
    except KeyError:
        raise UserError("%s flag must be one of: all, local" % flag)
Ejemplo n.º 5
0
    def logs(self, options):
        """
        View output from containers.

        Usage: logs [options] [SERVICE...]

        Options:
            --no-color          Produce monochrome output.
            -f, --follow        Follow log output.
            -t, --timestamps    Show timestamps.
            --tail="all"        Number of lines to show from the end of the logs
                                for each container.
        """
        containers = self.project.containers(service_names=options['SERVICE'],
                                             stopped=True)

        tail = options['--tail']
        if tail is not None:
            if tail.isdigit():
                tail = int(tail)
            elif tail != 'all':
                raise UserError("tail flag must be all or a number")
        log_args = {
            'follow': options['--follow'],
            'tail': tail,
            'timestamps': options['--timestamps']
        }
        print("Attaching to", list_containers(containers))
        log_printer_from_project(self.project,
                                 containers,
                                 options['--no-color'],
                                 log_args,
                                 event_stream=self.project.events(
                                     service_names=options['SERVICE'])).run()
Ejemplo n.º 6
0
def build_action_from_opts(options):
    if options['--build'] and options['--no-build']:
        raise UserError("--build and --no-build can not be combined.")

    if options['--build']:
        return BuildAction.force

    if options['--no-build']:
        return BuildAction.skip

    return BuildAction.none
Ejemplo n.º 7
0
 def load_project_config(self, options):
     explicit_config_path = options.get('--file')\
         or os.environ.get('COMPOSE_FILE')\
         or os.environ.get('FIG_FILE')
     config_path = self.get_config_path(file_path=explicit_config_path)
     try:
         with open(config_path, 'r') as fh:
             config = yaml.safe_load(fh)
             voodoo_config = config.pop('voodoo', {})
             self.set_config(voodoo_config)
     except IOError as e:
         raise UserError(six.text_type(e))
Ejemplo n.º 8
0
    def exec_command(self, options):
        """
        Execute a command in a running container

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

        Options:
            -d                Detached mode: Run command in the background.
            --privileged      Give extended privileges to the process.
            --user USER       Run the command as this user.
            -T                Disable pseudo-tty allocation. By default `docker-compose exec`
                              allocates a TTY.
            --index=index     index of the container if there are multiple
                              instances of a service [default: 1]
        """
        index = int(options.get('--index'))
        service = self.project.get_service(options['SERVICE'])
        try:
            container = service.get_container(number=index)
        except ValueError as e:
            raise UserError(str(e))
        command = [options['COMMAND']] + options['ARGS']
        tty = not options["-T"]

        create_exec_options = {
            "privileged": options["--privileged"],
            "user": options["--user"],
            "tty": tty,
            "stdin": tty,
        }

        exec_id = container.create_exec(command, **create_exec_options)
        print exec_id

        if options['-d']:
            print container.start_exec(exec_id, tty=tty)
            print "option -d"
            return

        signals.set_signal_handler_to_shutdown()
        try:
            operation = ExecOperation(
                self.project.client,
                exec_id,
                interactive=tty,
            )
            print "Pseudo Terminal"
            pty = PseudoTerminal(self.project.client, operation)
            pty.start()
        except signals.ShutdownException:
            log.info("received shutdown exception: closing")
        exit_code = self.project.client.exec_inspect(exec_id).get("ExitCode")
        sys.exit(exit_code)
Ejemplo n.º 9
0
def convergence_strategy_from_opts(options):
    no_recreate = options['--no-recreate']
    force_recreate = options['--force-recreate']
    if force_recreate and no_recreate:
        raise UserError(
            "--force-recreate and --no-recreate cannot be combined.")

    if force_recreate:
        return ConvergenceStrategy.always

    if no_recreate:
        return ConvergenceStrategy.never

    return ConvergenceStrategy.changed
Ejemplo n.º 10
0
    def port(self, options):
        """
        Print the public port for a port binding.

        Usage: port [options] SERVICE PRIVATE_PORT

        Options:
            --protocol=proto  tcp or udp [default: tcp]
            --index=index     index of the container if there are multiple
                              instances of a service [default: 1]
        """
        index = int(options.get('--index'))
        service = self.project.get_service(options['SERVICE'])
        try:
            container = service.get_container(number=index)
        except ValueError as e:
            raise UserError(str(e))
        print(
            container.get_local_port(options['PRIVATE_PORT'],
                                     protocol=options.get('--protocol')
                                     or 'tcp') or '')
Ejemplo n.º 11
0
    def up(self, options):
        """
        Builds, (re)creates, starts, and attaches to containers for a service.

        Unless they are already running, this command also starts any linked services.

        The `docker-compose up` command aggregates the output of each container. When
        the command exits, all containers are stopped. Running `docker-compose up -d`
        starts the containers in the background and leaves them running.

        If there are existing containers for a service, and the service's configuration
        or image was changed after the container's creation, `docker-compose up` picks
        up the changes by stopping and recreating the containers (preserving mounted
        volumes). To prevent Compose from picking up changes, use the `--no-recreate`
        flag.

        If you want to force Compose to stop and recreate all containers, use the
        `--force-recreate` flag.

        Usage: up [options] [SERVICE...]

        Options:
            -d                         Detached mode: Run containers in the background,
                                       print new container names.
                                       Incompatible with --abort-on-container-exit.
            --no-color                 Produce monochrome output.
            --no-deps                  Don't start linked services.
            --force-recreate           Recreate containers even if their configuration
                                       and image haven't changed.
                                       Incompatible with --no-recreate.
            --no-recreate              If containers already exist, don't recreate them.
                                       Incompatible with --force-recreate.
            --no-build                 Don't build an image, even if it's missing.
            --build                    Build images before starting containers.
            --abort-on-container-exit  Stops all containers if any container was stopped.
                                       Incompatible with -d.
            -t, --timeout TIMEOUT      Use this timeout in seconds for container shutdown
                                       when attached or when containers are already
                                       running. (default: 10)
            --remove-orphans           Remove containers for services not
                                       defined in the Compose file
        """
        start_deps = not options['--no-deps']
        cascade_stop = options['--abort-on-container-exit']
        service_names = options['SERVICE']
        timeout = int(options.get('--timeout') or DEFAULT_TIMEOUT)
        remove_orphans = options['--remove-orphans']
        detached = options.get('-d')

        if detached and cascade_stop:
            raise UserError(
                "--abort-on-container-exit and -d cannot be combined.")

        with up_shutdown_context(self.project, service_names, timeout,
                                 detached):
            to_attach = self.project.up(
                service_names=service_names,
                start_deps=start_deps,
                strategy=convergence_strategy_from_opts(options),
                do_build=build_action_from_opts(options),
                timeout=timeout,
                detached=detached,
                remove_orphans=remove_orphans)

            if detached:
                return

            log_printer = log_printer_from_project(
                self.project,
                filter_containers_to_service_names(to_attach, service_names),
                options['--no-color'], {'follow': True},
                cascade_stop,
                event_stream=self.project.events(service_names=service_names))
            print("Attaching to", list_containers(log_printer.containers))
            log_printer.run()

            if cascade_stop:
                print("Aborting on container exit...")
                self.project.stop(service_names=service_names, timeout=timeout)