refactor: simplified api call functions

jef
Jef Roosens 2022-06-21 15:47:42 +02:00
parent 26357f47b5
commit 3bda79f7ce
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 67 additions and 28 deletions

View File

@ -1,12 +1,15 @@
module vdocker module vdocker
import json import json
import net.urllib
import time import time
import net.http { Method } import net.http { Method }
struct DockerError { pub struct ContainerListItem {
message string id string [json: Id]
names []string [json: Names]
image string [json: Image]
image_id string [json: ImageID]
command string [json: Command]
} }
pub struct NewContainer { pub struct NewContainer {
@ -26,7 +29,7 @@ pub:
// create_container creates a new container with the given config. // create_container creates a new container with the given config.
pub fn (mut d DockerConn) create_container(c NewContainer) ?CreatedContainer { pub fn (mut d DockerConn) create_container(c NewContainer) ?CreatedContainer {
d.send_request_with_json(Method.post, urllib.parse('/v1.41/containers/create')?, c)? d.send_request_with_json(Method.post, '/containers/create', c)?
head, res := d.read_response()? head, res := d.read_response()?
if head.status_code != 201 { if head.status_code != 201 {
@ -42,7 +45,7 @@ pub fn (mut d DockerConn) create_container(c NewContainer) ?CreatedContainer {
// start_container starts the container with the given id. // start_container starts the container with the given id.
pub fn (mut d DockerConn) start_container(id string) ? { pub fn (mut d DockerConn) start_container(id string) ? {
d.send_request(Method.post, urllib.parse('/v1.41/containers/$id/start')?)? d.send_request(Method.post, 'containers/$id/start')?
head, body := d.read_response()? head, body := d.read_response()?
if head.status_code != 204 { if head.status_code != 204 {
@ -72,7 +75,7 @@ pub mut:
// inspect_container returns detailed information for a given container. // inspect_container returns detailed information for a given container.
pub fn (mut d DockerConn) inspect_container(id string) ?ContainerInspect { pub fn (mut d DockerConn) inspect_container(id string) ?ContainerInspect {
d.send_request(Method.get, urllib.parse('/v1.41/containers/$id/json')?)? d.send_request(Method.get, 'containers/$id/json')?
head, body := d.read_response()? head, body := d.read_response()?
if head.status_code != 200 { if head.status_code != 200 {
@ -95,7 +98,7 @@ pub fn (mut d DockerConn) inspect_container(id string) ?ContainerInspect {
// remove_container removes the container with the given id. // remove_container removes the container with the given id.
pub fn (mut d DockerConn) remove_container(id string) ? { pub fn (mut d DockerConn) remove_container(id string) ? {
d.send_request(Method.delete, urllib.parse('/v1.41/containers/$id')?)? d.send_request(Method.delete, 'containers/$id')?
head, body := d.read_response()? head, body := d.read_response()?
if head.status_code != 204 { if head.status_code != 204 {
@ -108,7 +111,7 @@ pub fn (mut d DockerConn) remove_container(id string) ? {
// get_container_logs returns a reader object allowing access to the // get_container_logs returns a reader object allowing access to the
// container's logs. // container's logs.
pub fn (mut d DockerConn) get_container_logs(id string) ?&StreamFormatReader { pub fn (mut d DockerConn) get_container_logs(id string) ?&StreamFormatReader {
d.send_request(Method.get, urllib.parse('/v1.41/containers/$id/logs?stdout=true&stderr=true')?)? d.send_request(Method.get, 'containers/$id/logs?stdout=true&stderr=true')?
head := d.read_response_head()? head := d.read_response_head()?
if head.status_code != 200 { if head.status_code != 200 {

View File

@ -7,12 +7,15 @@ import strings
import net.urllib import net.urllib
import json import json
import util import util
import time
const ( const (
socket = '/var/run/docker.sock' socket = '/var/run/docker.sock'
buf_len = 10 * 1024 buf_len = 10 * 1024
http_separator = [u8(`\r`), `\n`, `\r`, `\n`] http_separator = [u8(`\r`), `\n`, `\r`, `\n`]
http_chunk_separator = [u8(`\r`), `\n`] http_chunk_separator = [u8(`\r`), `\n`]
timestamp_attr = 'timestamp'
api_version = 'v1.41'
) )
pub struct DockerConn { pub struct DockerConn {
@ -39,7 +42,8 @@ pub fn (mut d DockerConn) close() ? {
} }
// send_request sends an HTTP request without body. // send_request sends an HTTP request without body.
fn (mut d DockerConn) send_request(method http.Method, url urllib.URL) ? { fn (mut d DockerConn) send_request(method http.Method, url_str string) ? {
url := urllib.parse('/$api_version$url_str')?
req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n' req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n'
d.socket.write_string(req)? d.socket.write_string(req)?
@ -49,7 +53,8 @@ fn (mut d DockerConn) send_request(method http.Method, url urllib.URL) ? {
} }
// send_request_with_body sends an HTTP request with the given body. // send_request_with_body sends an HTTP request with the given body.
fn (mut d DockerConn) send_request_with_body(method http.Method, url urllib.URL, content_type string, body string) ? { fn (mut d DockerConn) send_request_with_body(method http.Method, url_str string, content_type string, body string) ? {
url := urllib.parse('/$api_version$url_str')?
req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Type: $content_type\nContent-Length: $body.len\n\n$body\n\n' req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\nContent-Type: $content_type\nContent-Length: $body.len\n\n$body\n\n'
d.socket.write_string(req)? d.socket.write_string(req)?
@ -60,10 +65,10 @@ fn (mut d DockerConn) send_request_with_body(method http.Method, url urllib.URL,
// send_request_with_json<T> is a convenience wrapper around // send_request_with_json<T> is a convenience wrapper around
// send_request_with_body that encodes the input as JSON. // send_request_with_body that encodes the input as JSON.
fn (mut d DockerConn) send_request_with_json<T>(method http.Method, url urllib.URL, data &T) ? { fn (mut d DockerConn) send_request_with_json<T>(method http.Method, url_str string, data &T) ? {
body := json.encode(data) body := json.encode(data)
return d.send_request_with_body(method, url, 'application/json', body) return d.send_request_with_body(method, url_str, 'application/json', body)
} }
// read_response_head consumes the socket's contents until it encounters // read_response_head consumes the socket's contents until it encounters
@ -119,6 +124,26 @@ fn (mut d DockerConn) read_response() ?(http.Response, string) {
return head, res return head, res
} }
fn (mut d DockerConn) read_json_response<T>() ?T {
head, body := d.read_response()?
if head.status_code < 200 || head.status_code > 300 {
data := json.decode(DockerError, body)?
return docker_error(head.status_code, data.message)
}
mut data := json.decode(T, body)?
/* $for field in T.fields { */
/* $if field.typ is time.Time { */
/* data.$(field.name) = time.parse_rfc3339(data.$(field.name + '_str'))? */
/* } */
/* } */
return data
}
// get_chunked_response_reader returns a ChunkedResponseReader using the socket // get_chunked_response_reader returns a ChunkedResponseReader using the socket
// as reader. // as reader.
fn (mut d DockerConn) get_chunked_response_reader() &ChunkedResponseReader { fn (mut d DockerConn) get_chunked_response_reader() &ChunkedResponseReader {

21
errors.v 100644
View File

@ -0,0 +1,21 @@
module vdocker
struct DockerError {
status int [skip]
message string
}
fn (err DockerError) code() int {
return err.status
}
fn (err DockerError) msg() string {
return err.message
}
fn docker_error(status int, message string) IError {
return IError(DockerError{
status: status
message: message
})
}

View File

@ -1,7 +1,6 @@
module vdocker module vdocker
import net.http { Method } import net.http { Method }
import net.urllib
import json import json
struct Image { struct Image {
@ -11,7 +10,7 @@ pub:
// pull_image pulls the given image:tag. // pull_image pulls the given image:tag.
pub fn (mut d DockerConn) pull_image(image string, tag string) ? { pub fn (mut d DockerConn) pull_image(image string, tag string) ? {
d.send_request(Method.post, urllib.parse('/v1.41/images/create?fromImage=$image&tag=$tag')?)? d.send_request(Method.post, 'images/create?fromImage=$image&tag=$tag')?
head := d.read_response_head()? head := d.read_response_head()?
if head.status_code != 200 { if head.status_code != 200 {
@ -34,7 +33,7 @@ pub fn (mut d DockerConn) pull_image(image string, tag string) ? {
// create_image_from_container creates a new image from a container. // create_image_from_container creates a new image from a container.
pub fn (mut d DockerConn) create_image_from_container(id string, repo string, tag string) ?Image { pub fn (mut d DockerConn) create_image_from_container(id string, repo string, tag string) ?Image {
d.send_request(Method.post, urllib.parse('/v1.41/commit?container=$id&repo=$repo&tag=$tag')?)? d.send_request(Method.post, 'commit?container=$id&repo=$repo&tag=$tag')?
head, body := d.read_response()? head, body := d.read_response()?
if head.status_code != 201 { if head.status_code != 201 {
@ -50,7 +49,7 @@ pub fn (mut d DockerConn) create_image_from_container(id string, repo string, ta
// remove_image removes the image with the given id. // remove_image removes the image with the given id.
pub fn (mut d DockerConn) remove_image(id string) ? { pub fn (mut d DockerConn) remove_image(id string) ? {
d.send_request(Method.delete, urllib.parse('/v1.41/images/$id')?)? d.send_request(Method.delete, 'images/$id')?
head, body := d.read_response()? head, body := d.read_response()?
if head.status_code != 200 { if head.status_code != 200 {

View File

@ -1,8 +1,6 @@
module vdocker module vdocker
import net.http { Method } import net.http { Method }
import net.urllib
import json
import time import time
struct UsageData { struct UsageData {
@ -13,10 +11,10 @@ struct UsageData {
struct Volume { struct Volume {
created_at_str string [json: CreatedAt] created_at_str string [json: CreatedAt]
pub mut: pub mut:
created_at time.Time [skip]
name string [json: Name] name string [json: Name]
driver string [json: Driver] driver string [json: Driver]
mountpoint string [json: Mountpoint] mountpoint string [json: Mountpoint]
created_at time.Time [skip]
status map[string]string [json: Status] status map[string]string [json: Status]
labels map[string]string [json: Labels] labels map[string]string [json: Labels]
scope string [json: Scope] scope string [json: Scope]
@ -30,16 +28,9 @@ struct VolumeListResponse {
} }
pub fn (mut d DockerConn) volume_list() ?VolumeListResponse { pub fn (mut d DockerConn) volume_list() ?VolumeListResponse {
d.send_request(Method.get, urllib.parse('/v1.41/volumes')?)? d.send_request(Method.get, '/volumes')?
head, body := d.read_response()?
if head.status_code != 200 { mut data := d.read_json_response<VolumeListResponse>()?
data := json.decode(DockerError, body)?
return error(data.message)
}
mut data := json.decode(VolumeListResponse, body)?
for mut vol in data.volumes { for mut vol in data.volumes {
vol.created_at = time.parse_rfc3339(vol.created_at_str)? vol.created_at = time.parse_rfc3339(vol.created_at_str)?