Beispiel #1
0
    def logs(
        self,
        services: Union[str, List[str]] = [],
        tail: Optional[str] = None,
        follow: bool = False,
        no_log_prefix: bool = False,
        timestamps: bool = False,
        since: Optional[str] = None,
        until: Optional[str] = None,
        stream: bool = False,
    ):
        """View output from containers

        # Arguments
            services: One or more service(s) to view
            tail: Number of lines to show from the end of the logs for each container. (default "all")
            follow: Follow log output ***WARNING***: With this
                option, `docker.compose.logs()` will not return at all. Use it exclusively with
                `stream=True`. You can loop on the logs but the loop will never end.

            no_log_prefix: Don't print prefix in logs
            timestamps: Show timestamps
            since: Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
            until: Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m for 42 minutes)
            stream: Similar to the `stream` argument of `docker.run()`.
                This function will then returns and iterator that will yield a
                tuple `(source, content)` with `source` being `"stderr"` or
                `"stdout"`. `content` is the content of the line as bytes.
                Take a look at [the user guide](https://gabrieldemarmiesse.github.io/python-on-whales/user_guide/docker_run/#stream-the-output)
                to have an example of the output.
        # Returns
            `str` if `stream=False` (the default), `Iterable[Tuple[str, bytes]]`
            if `stream=True`.
        """
        full_cmd = self.docker_compose_cmd + ["logs", "--no-color"]
        full_cmd.add_simple_arg("--tail", tail)
        full_cmd.add_flag("--follow", follow)
        full_cmd.add_flag("--no-log-prefix", no_log_prefix)
        full_cmd.add_flag("--timestamps", timestamps)
        full_cmd.add_simple_arg("--since", since)
        full_cmd.add_simple_arg("--until", until)
        full_cmd += to_list(services)

        iterator = stream_stdout_and_stderr(full_cmd)
        if stream:
            return iterator
        else:
            return "".join(x[1].decode() for x in iterator)
Beispiel #2
0
    def load(self,
             input: Union[ValidPath, bytes, Iterator[bytes]],
             quiet: bool = False) -> List[str]:
        """Loads one or multiple Docker image(s) from a tar or an iterator of `bytes`.

        Alias: `docker.load(...)`

        # Arguments
            input: Path or input stream to load the images from.
            quiet: If you don't want to display the progress bars.

        # Returns
            `None` when using bytes as input. A `List[str]` (list of tags)
             when a path is provided.
        """
        full_cmd = self.docker_cmd + ["image", "load"]

        if isinstance(input, (str, Path)):
            full_cmd += ["--input", str(input)]

        if quiet:
            full_cmd.append("--quiet")

        if isinstance(input, (str, Path)):
            all_tags = []
            for source, stream_bytes in stream_stdout_and_stderr(full_cmd):
                decoded = stream_bytes.decode()[:-1]
                if not quiet:
                    print(decoded)
                if "Loaded image" in decoded:
                    all_tags.append(decoded.split(" ")[-1])
            return all_tags

        if isinstance(input, bytes):
            input = [input]

        stdout_lines = self._load_from_generator(full_cmd, input)
        all_tags = []
        for line in stdout_lines:
            if "Loaded image" in line:
                all_tags.append(line.split(" ")[-1])
        return all_tags
Beispiel #3
0
    def run(
        self,
        service: str,
        command: List[str] = [],
        detach: bool = False,
        # entrypoint: Optional[List[str]] = None,
        # envs: Dict[str, str] = {},
        # labels: Dict[str, str] = {},
        name: Optional[str] = None,
        tty: bool = True,
        stream: bool = False,
        dependencies: bool = True,
        publish: List[python_on_whales.components.container.cli_wrapper.
                      ValidPortMapping] = [],
        remove: bool = False,
        service_ports: bool = False,
        use_aliases: bool = False,
        user: Optional[str] = None,
        # volumes: bool = "todo",
        workdir: Union[None, str, Path] = None,
    ) -> Union[str, python_on_whales.components.container.cli_wrapper.
               Container, Iterable[Tuple[str, bytes]], ]:
        """Run a one-off command on a service.

        # Arguments
            service: The name of the service.
            command: The command to execute.
            detach: if `True`, returns immediately with the Container.
                    If `False`, returns the command stdout as string.
            name: Assign a name to the container.
            dependencies: Also start linked services.
            publish: Publish a container's port(s) to the host.
            service_ports: Enable service's ports and map them to the host.
            remove: Automatically remove the container when it exits.
            use_aliases: Use the service's network aliases in the connected network(s).
            tty: Allocate a pseudo-TTY. Allow the process to access your terminal
                to write on it.
            stream: Similar to `docker.run(..., stream=True)`.
            user: Username or UID, format: `"<name|uid>[:<group|gid>]"`
            workdir: Working directory inside the container

        # Returns:
            Optional[str]

        """

        if tty and stream:
            raise ValueError(
                "You can't set tty=True and stream=True at the same"
                "time. Their purpose are not compatible. Try setting tty=False in docker.compose.run"
            )

        if detach and stream:
            raise ValueError(
                "You can't detach and stream at the same time. It's not compatible."
            )

        if detach and tty:
            raise ValueError(
                "You can't detach and set tty=True at the same time. It's not compatible. "
                "Try setting tty=False in docker.compose.run(...).")
        full_cmd = self.docker_compose_cmd + ["run"]
        full_cmd.add_flag("--detach", detach)
        full_cmd.add_simple_arg("--name", name)
        full_cmd.add_flag("--no-TTY", not tty)
        full_cmd.add_flag("--no-deps", not dependencies)
        for port_mapping in publish:
            if len(port_mapping) == 2:
                full_cmd += [
                    "--publish", f"{port_mapping[0]}:{port_mapping[1]}"
                ]
            else:
                full_cmd += [
                    "--publish",
                    f"{port_mapping[0]}:{port_mapping[1]}/{port_mapping[2]}",
                ]

        full_cmd.add_flag("--rm", remove)
        full_cmd.add_flag("--service-ports", service_ports)
        full_cmd.add_flag("--use-aliases", use_aliases)
        full_cmd.add_simple_arg("--user", user)
        full_cmd.add_simple_arg("--workdir", workdir)
        full_cmd.append(service)
        full_cmd += command

        if stream:
            return stream_stdout_and_stderr(full_cmd)
        else:
            result = run(full_cmd, tty=tty)
            if detach:
                Container = python_on_whales.components.container.cli_wrapper.Container
                return Container(self.client_config,
                                 result,
                                 is_immutable_id=True)
            else:
                return result
Beispiel #4
0
    def logs(
        self,
        service: ValidService,
        details: bool = False,
        since: Union[None, datetime, timedelta] = None,
        tail: Optional[int] = None,
        timestamps: bool = False,
        follow: bool = False,
        raw: bool = False,
        task_ids: bool = True,
        resolve: bool = True,
        truncate: bool = True,
        stream: bool = False,
    ):
        """Returns the logs of a service as a string or an iterator.

        # Arguments
            service: The service to get the logs of
            details: Show extra details provided to logs
            since: Use a datetime or timedelta to specify the lower
                date limit for the logs.
            tail: Number of lines to show from the end of the logs (default all)
            timestamps: Put timestamps next to lines.
            follow: If `False` (the default), the logs returned are the logs up to the time
                of the function call. If `True`, the logs of the container up to the time the
                service is stopped (removed) are displayed.
                Which is why you must use the `stream` option if you use the `follow` option.
                Without `stream`, only a `str` will be returned, possibly much later in the
                future (maybe never if the service is never removed). So this option is not
                possible (You'll get an error if you use follow and not stream).
                With `stream`, you'll be able to read the logs in real time and stop
                whenever you need.
            stream: Similar to the `stream` argument of `docker.run()`.
                This function will then returns and iterator that will yield a
                tuple `(source, content)` with `source` being `"stderr"` or
                `"stdout"`. `content` is the content of the line as bytes.
                Take a look at [the user guide](https://gabrieldemarmiesse.github.io/python-on-whales/user_guide/docker_run/#stream-the-output)
                to have an example of the output.

        # Returns
            `str` if `stream=False` (the default), `Iterable[Tuple[str, bytes]]`
            if `stream=True`.

        # Raises
            `python_on_whales.exceptions.NoSuchService` if the service does not exists.
        """
        # first we verify that the service exists and raise an exception if not.
        self.inspect(str(service))

        full_cmd = self.docker_cmd + ["service", "logs"]
        full_cmd.add_flag("--details", details)
        full_cmd.add_simple_arg("--since", format_time_arg(since))
        full_cmd.add_simple_arg("--tail", tail)
        full_cmd.add_flag("--timestamps", timestamps)
        full_cmd.add_flag("--follow", follow)
        full_cmd.add_flag("--raw", raw)
        full_cmd.add_flag("--no-task-ids", not task_ids)
        full_cmd.add_flag("--no-resolve", not resolve)
        full_cmd.add_flag("--no-trunc", not truncate)
        full_cmd.append(service)

        iterator = stream_stdout_and_stderr(full_cmd)
        if stream:
            return iterator
        else:
            return "".join(x[1].decode() for x in iterator)
Beispiel #5
0
def stream_buildx_logs(full_cmd: list,
                       env: Dict[str, str] = None) -> Iterator[str]:
    for origin, value in stream_stdout_and_stderr(full_cmd, env=env):
        yield value.decode()