diff --git a/src/build/build.v b/src/build/build.v index b470853..ae10318 100644 --- a/src/build/build.v +++ b/src/build/build.v @@ -56,6 +56,7 @@ pub fn create_build_image(base_image string) ?string { // This loop waits until the container has stopped, so we can remove it after for { + println('wot') data := dd.inspect_container(id)? if !data.state.running { diff --git a/src/docker/containers.v b/src/docker/containers.v index 98116cc..e2da938 100644 --- a/src/docker/containers.v +++ b/src/docker/containers.v @@ -5,6 +5,10 @@ import net.urllib import time import net.http +struct DockerError { + message string +} + struct Container { id string [json: Id] names []string [json: Names] @@ -12,7 +16,13 @@ struct Container { pub fn (mut d DockerDaemon) containers() ?[]Container { d.send_request('GET', urllib.parse('/v1.41/containers/json')?)? - _, res := d.read_response()? + head, res := d.read_response()? + + if head.status_code != 200 { + data := json.decode(DockerError, res)? + + return error(data.message) + } data := json.decode([]Container, res)? @@ -37,18 +47,28 @@ pub: pub fn (mut d DockerDaemon) create_container(c NewContainer) ?CreatedContainer { d.send_request_with_json('POST', urllib.parse('/v1.41/containers/create')?, c)? - _, res := d.read_response()? + head, res := d.read_response()? + + if head.status_code != 201 { + data := json.decode(DockerError, res)? + + return error(data.message) + } data := json.decode(CreatedContainer, res)? return data } -pub fn (mut d DockerDaemon) start_container(id string) ?bool { +pub fn (mut d DockerDaemon) start_container(id string) ? { d.send_request('POST', urllib.parse('/v1.41/containers/$id/start')?)? - head := d.read_response_head() ? + head, body := d.read_response() ? - return head.status_code == 204 + if head.status_code != 204 { + data := json.decode(DockerError, body)? + + return error(data.message) + } } // create_container creates a container defined by the given configuration. If @@ -94,7 +114,9 @@ pub fn (mut d DockerDaemon) inspect_container(id string) ?ContainerInspect { head, body := d.read_response()? if head.status_code != 200 { - return error('Failed to inspect container.') + data := json.decode(DockerError, body)? + + return error(data.message) } mut data := json.decode(ContainerInspect, body)? @@ -130,7 +152,13 @@ pub fn inspect_container(id string) ?ContainerInspect { pub fn (mut d DockerDaemon) remove_container(id string) ? { d.send_request('DELETE', urllib.parse('/v1.41/containers/$id')?)? - head := d.read_response_head() ? + head, body := d.read_response() ? + + if head.status_code != 204 { + data := json.decode(DockerError, body)? + + return error(data.message) + } } // remove_container removes a container with a given ID. diff --git a/src/docker/socket.v b/src/docker/socket.v index 41f9f6d..749f14e 100644 --- a/src/docker/socket.v +++ b/src/docker/socket.v @@ -50,6 +50,8 @@ pub fn (mut d DockerDaemon) send_request_with_json(method string, url urllib. // read_response_head consumes the socket's contents until it encounters // '\r\n\r\n', after which it parses the response as an HTTP response. +// Importantly, this function never consumes past the HTTP separator, so the +// body can be read fully later on. pub fn (mut d DockerDaemon) read_response_head() ?http.Response { mut c := 0 mut buf := []u8{len: 4} @@ -88,6 +90,10 @@ pub fn (mut d DockerDaemon) read_response_head() ?http.Response { } pub fn (mut d DockerDaemon) read_response_body(length int) ?string { + if length == 0 { + return '' + } + mut buf := []u8{len: docker.buf_len} mut c := 0 mut builder := strings.new_builder(docker.buf_len) diff --git a/src/docker/stream.v b/src/docker/stream.v new file mode 100644 index 0000000..24c51c1 --- /dev/null +++ b/src/docker/stream.v @@ -0,0 +1,9 @@ +module docker + +import io + +struct ChunkedResponseStream { + reader io.Reader +} + +