Beispiel #1
0
    def response_reader():
        """Read remote command responses from the socket."""

        for stream_type, data in frames_iter(socket, tty=False):
            response = data.decode("utf-8")
            if stream_type == 1:
                # stream_type == 1 means it's from the command's stdout
                logger.debug("received: %s", response.encode("utf-8"))
                try:
                    msg = json.loads(response)
                    if "result" in msg and "file" in msg["result"]:
                        container_file = Path(msg["result"]["file"])
                        volume_file = container_path_to_volume_path(
                            container_file)
                        msg["result"]["file"] = str(volume_file)
                        response = json.dumps(msg) + "\n"
                except Exception as e:
                    logger.warning(
                        "Cannot parse gftp response '%s': %s",
                        response.encode("utf-8"),
                        e,
                    )
                    # Return the response as is
                sys.stdout.write(response)
                sys.stdout.flush()
            elif stream_type == 2:
                # it's from the command's stderr
                logger.debug("stderr: %s", response.strip())
            else:
                raise ValueError(
                    f"Unexpected stream type in a frame header: {stream_type}")
Beispiel #2
0
    def _read_from_sock(self, sock: socket, tty: bool):
        """Reads multiplexed messages from a socket returned by attach_socket.

        Uses the protocol specified here: https://docs.docker.com/engine/api/v1.41/#operation/ContainerAttach
        """
        stdout = b""
        stderr = b""
        for frame_type, frame_data in frames_iter(sock, tty):
            if frame_type == STDOUT:
                stdout += frame_data
            elif frame_type == STDERR:
                stderr += frame_data
            else:
                raise ContainerException("Invalid frame type when reading from socket")
        return stdout, stderr
Beispiel #3
0
    def read(self) -> str:
        """
        Generator yielding lines read from socket.
        :return:                Lines read from socket (str)
        """
        read_buffer = ""

        for stream, frame in frames_iter(socket=self.socket, tty=False):

            read_buffer += frame.decode("utf8")

            if read_buffer.endswith("\n"):
                yield read_buffer.strip("\n")
                read_buffer = ""

        if read_buffer:
            yield read_buffer.strip("\n")
Beispiel #4
0
    def read(self) -> str:
        """
        Generator yielding lines read from named pipe. Retry mechanism tries to avoid breaking
        prematurely while waiting on the other end of the pipe to send data.
        :return:                Lines read from named pipe (str)
        """
        read_buffer = ""

        max_peek_tries = 3

        for stream, frame in frames_iter(socket=self.socket, tty=False):

            read_buffer += frame.decode("utf8")

            if read_buffer.endswith("\n"):
                yield read_buffer.strip("\n")
                read_buffer = ""

            peek_tries = 0

            while peek_tries <= max_peek_tries:

                _, n_bytes_left, _ = win32pipe.PeekNamedPipe(self.socket._handle, 2)

                if n_bytes_left:
                    break
                else:
                    self.logger.debug("No bytes left to read. Retrying...")
                    self.logger.debug("peek_tries: %s", peek_tries)
                    peek_tries += 1
                    time.sleep(1)
                    continue
            else:
                self.logger.debug("No more bytes left to read")

                if read_buffer:
                    yield read_buffer.strip("\n")

                break
Beispiel #5
0
def read_socket(sock, timeout: int = None) -> Tuple[bytes, bytes]:
    """
    Reads from a docker socket, and returns everything
    :param sock: Docker socket to read from
    :param timeout: Number of seconds after which we return all data collected
    :return: A tuple of stdout, stderr
    """
    start_time = time.time()
    out = [b"", b""]
    for frame in frames_iter(sock, tty=False):
        frame = demux_adaptor(*frame)

        # If we hit the timeout, return anyawy
        if time.time() >= start_time + timeout:
            return tuple(out)

        assert frame != (None, None)

        if frame[0] is not None:
            out[0] += frame[0]
        else:
            out[1] += frame[1]
    return tuple(out)