From f22ed29631a3e5d09b9496bb6bba255d4b5dc400 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sat, 14 May 2022 22:39:52 +0200 Subject: [PATCH] feat(docker): added StreamFormatReader --- src/docker/containers.v | 15 +++++++++ src/docker/socket.v | 7 ++++ src/docker/stream.v | 73 ++++++++++++++++++++++++++++++++++------- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/src/docker/containers.v b/src/docker/containers.v index 0027747..ff48c69 100644 --- a/src/docker/containers.v +++ b/src/docker/containers.v @@ -168,6 +168,21 @@ pub fn remove_container(id string) ?bool { return res.status_code == 204 } +pub fn (mut d DockerDaemon) get_container_logs(id string) ?&StreamFormatReader { + d.send_request('GET', urllib.parse('/v1.41/containers/$id/logs?stdout=true&stderr=true')?)? + head := d.read_response_head()? + + if head.status_code != 200 { + content_length := head.header.get(http.CommonHeader.content_length)?.int() + body := d.read_response_body(content_length)? + data := json.decode(DockerError, body)? + + return error(data.message) + } + + return d.get_stream_format_reader() +} + // get_container_logs retrieves the logs for a Docker container, both stdout & // stderr. pub fn get_container_logs(id string) ?string { diff --git a/src/docker/socket.v b/src/docker/socket.v index 444d9a9..f6dfeb1 100644 --- a/src/docker/socket.v +++ b/src/docker/socket.v @@ -123,3 +123,10 @@ pub fn (mut d DockerDaemon) get_chunked_response_reader() &ChunkedResponseReader return r } + +pub fn (mut d DockerDaemon) get_stream_format_reader() &StreamFormatReader { + r := new_chunked_response_reader(d.reader) + r2 := new_stream_format_reader(r) + + return r2 +} diff --git a/src/docker/stream.v b/src/docker/stream.v index fbc48ba..8822fd3 100644 --- a/src/docker/stream.v +++ b/src/docker/stream.v @@ -7,13 +7,10 @@ import encoding.hex struct ChunkedResponseReader { mut: - reader io.Reader - // buf []u8 - // offset int - // len int + reader io.Reader bytes_left_in_chunk u64 end_of_stream bool - started bool + started bool } pub fn new_chunked_response_reader(reader io.Reader) &ChunkedResponseReader { @@ -39,7 +36,7 @@ pub fn (mut r ChunkedResponseReader) read(mut buf []u8) ?int { } mut c := 0 - + if buf.len > r.bytes_left_in_chunk { c = r.reader.read(mut buf[..r.bytes_left_in_chunk])? } else { @@ -56,8 +53,8 @@ fn (mut r ChunkedResponseReader) read_chunk_size() ?u64 { mut res := []u8{} if r.started { - // Each chunk ends with a `\r\n` which we want to skip first - r.reader.read(mut buf) ? + // Each chunk ends with a `\r\n` which we want to skip first + r.reader.read(mut buf)? } r.started = true @@ -85,9 +82,9 @@ fn (mut r ChunkedResponseReader) read_chunk_size() ?u64 { mut num_data := hex.decode(res#[..-2].bytestr())? - for num_data.len < 8 { - num_data.insert(0, 0) - } + for num_data.len < 8 { + num_data.insert(0, 0) + } num := binary.big_endian_u64(num_data) @@ -97,3 +94,57 @@ fn (mut r ChunkedResponseReader) read_chunk_size() ?u64 { return num } + +struct StreamFormatReader { + stdout bool + stderr bool + stdin bool +mut: + reader io.Reader + bytes_left_in_chunk u32 + end_of_stream bool +} + +pub fn new_stream_format_reader(reader io.Reader) &StreamFormatReader { + r := &StreamFormatReader{ + reader: reader + } + + return r +} + +pub fn (mut r StreamFormatReader) read(mut buf []u8) ?int { + if r.end_of_stream { + return none + } + + if r.bytes_left_in_chunk == 0 { + r.bytes_left_in_chunk = r.read_chunk_size()? + + if r.end_of_stream { + return none + } + } + + mut c := 0 + + if buf.len > r.bytes_left_in_chunk { + c = r.reader.read(mut buf[..r.bytes_left_in_chunk])? + } else { + c = r.reader.read(mut buf)? + } + + r.bytes_left_in_chunk -= u32(c) + + return c +} + +fn (mut r StreamFormatReader) read_chunk_size() ?u32 { + mut buf := []u8{len: 8} + + r.reader.read(mut buf)? + + num := binary.big_endian_u32(buf[4..]) + + return num +}