Compare commits

..

No commits in common. "main" and "fix-segfaults" have entirely different histories.

8 changed files with 27 additions and 43 deletions

View File

@ -1,6 +1,3 @@
variables:
- &vlang_image 'git.rustybever.be/chewing_bever/vlang:0.3.3-alpine3.17'
branches: branches:
exclude: [ main ] exclude: [ main ]
@ -8,14 +5,14 @@ platform: 'linux/amd64'
pipeline: pipeline:
build: build:
image: *vlang_image image: 'git.rustybever.be/chewing_bever/vlang:0.3.2'
commands: commands:
- make - make
when: when:
event: [ push ] event: [ push ]
lint: lint:
image: *vlang_image image: 'git.rustybever.be/chewing_bever/vlang:0.3.2'
commands: commands:
- make lint - make lint
when: when:

View File

@ -20,7 +20,7 @@ reference](https://docs.docker.com/engine/api/v1.41/).
- [ ] Start a container - [ ] Start a container
- [ ] Stop a container - [ ] Stop a container
- [ ] Restart a container - [ ] Restart a container
- [x] Kill a container - [ ] Kill a container
- [ ] Update a container - [ ] Update a container
- [ ] Rename a container - [ ] Rename a container
- [ ] Pause a container - [ ] Pause a container

View File

@ -16,7 +16,7 @@ pub fn (mut d DockerConn) container_list(c ContainerListConfig) ![]ContainerList
d.params(c) d.params(c)
d.send()! d.send()!
return d.read_json_response[[]ContainerListItem]() return d.read_json_response<[]ContainerListItem>()
} }
pub struct NewContainer { pub struct NewContainer {
@ -39,12 +39,12 @@ pub fn (mut d DockerConn) container_create(c NewContainer) !CreatedContainer {
d.body_json(c) d.body_json(c)
d.send()! d.send()!
return d.read_json_response[CreatedContainer]() return d.read_json_response<CreatedContainer>()
} }
// start_container starts the container with the given id. // start_container starts the container with the given id.
pub fn (mut d DockerConn) container_start(id string) ! { pub fn (mut d DockerConn) container_start(id string) ! {
d.request(.post, '/containers/${id}/start') d.request(.post, '/containers/$id/start')
d.send()! d.send()!
d.read_response()! d.read_response()!
} }
@ -68,10 +68,10 @@ pub mut:
} }
pub fn (mut d DockerConn) container_inspect(id string) !ContainerInspect { pub fn (mut d DockerConn) container_inspect(id string) !ContainerInspect {
d.request(.get, '/containers/${id}/json') d.request(.get, '/containers/$id/json')
d.send()! d.send()!
mut data := d.read_json_response[ContainerInspect]()! mut data := d.read_json_response<ContainerInspect>()!
// The Docker engine API *should* always return UTC time. // The Docker engine API *should* always return UTC time.
data.state.start_time = time.parse_rfc3339(data.state.start_time_str)! data.state.start_time = time.parse_rfc3339(data.state.start_time_str)!
@ -84,19 +84,13 @@ pub fn (mut d DockerConn) container_inspect(id string) !ContainerInspect {
} }
pub fn (mut d DockerConn) container_remove(id string) ! { pub fn (mut d DockerConn) container_remove(id string) ! {
d.request(.delete, '/containers/${id}') d.request(.delete, '/containers/$id')
d.send()!
d.read_response()!
}
pub fn (mut d DockerConn) container_kill(id string) ! {
d.request(.post, '/containers/${id}/kill')
d.send()! d.send()!
d.read_response()! d.read_response()!
} }
pub fn (mut d DockerConn) container_get_logs(id string) !&StreamFormatReader { pub fn (mut d DockerConn) container_get_logs(id string) !&StreamFormatReader {
d.request(.get, '/containers/${id}/logs') d.request(.get, '/containers/$id/logs')
d.params({ d.params({
'stdout': 'true' 'stdout': 'true'
'stderr': 'true' 'stderr': 'true'

View File

@ -81,7 +81,7 @@ fn (mut d DockerConn) read_response_body() ! {
content_length := d.head.header.get(.content_length)!.int() content_length := d.head.header.get(.content_length)!.int()
if content_length == 0 { if content_length == 0 {
d.body = '' d.body = ''
return return
} }
@ -111,7 +111,7 @@ fn (mut d DockerConn) read_response() ! {
// read_json_response<T> is a convenience function that runs read_response // read_json_response<T> is a convenience function that runs read_response
// before parsing its contents, which is assumed to be JSON, into a struct. // before parsing its contents, which is assumed to be JSON, into a struct.
fn (mut d DockerConn) read_json_response[T]() !T { fn (mut d DockerConn) read_json_response<T>() !T {
d.read_response()! d.read_response()!
data := json.decode(T, d.body)! data := json.decode(T, d.body)!
@ -156,6 +156,6 @@ fn (mut d DockerConn) check_error() ! {
d.read_response_body()! d.read_response_body()!
d_err := json.decode(DockerError, d.body)! d_err := json.decode(DockerError, d.body)!
return error_with_code('${d.head.status()}: ${d_err.message}', d.head.status_code) return error_with_code('$d.head.status(): $d_err.message', d.head.status_code)
} }
} }

View File

@ -3,10 +3,10 @@ module docker
import types { Image } import types { Image }
pub fn (mut d DockerConn) image_inspect(image string) !Image { pub fn (mut d DockerConn) image_inspect(image string) !Image {
d.request(.get, '/images/${image}/json') d.request(.get, '/images/$image/json')
d.send()! d.send()!
data := d.read_json_response[Image]()! data := d.read_json_response<Image>()!
return data return data
} }
@ -40,21 +40,20 @@ pub fn (mut d DockerConn) image_from_container(id string, repo string, tag strin
'repo': repo 'repo': repo
'tag': tag 'tag': tag
}) })
d.body('application/json', '{}')
d.send()! d.send()!
return d.read_json_response[Image]()! return d.read_json_response<Image>()!
} }
// remove_image removes the image with the given id. // remove_image removes the image with the given id.
pub fn (mut d DockerConn) image_remove(id string) ! { pub fn (mut d DockerConn) image_remove(id string) ! {
d.request(.delete, '/images/${id}') d.request(.delete, '/images/$id')
d.send()! d.send()!
d.read_response()! d.read_response()!
} }
pub fn (mut d DockerConn) image_tag(name string, repo string, tag string) ! { pub fn (mut d DockerConn) image_tag(name string, repo string, tag string) ! {
d.request(.post, '/images/${name}/tag') d.request(.post, '/images/$name/tag')
d.params({ d.params({
'repo': repo 'repo': repo
'tag': tag 'tag': tag

View File

@ -19,12 +19,12 @@ fn (mut d DockerConn) body(content_type string, body string) {
d.body = body d.body = body
} }
fn (mut d DockerConn) body_json[T](data T) { fn (mut d DockerConn) body_json<T>(data T) {
d.content_type = 'application/json' d.content_type = 'application/json'
d.body = json.encode(data) d.body = json.encode(data)
} }
fn (mut d DockerConn) params[T](o T) { fn (mut d DockerConn) params<T>(o T) {
$if T is map[string]string { $if T is map[string]string {
for key, value in o { for key, value in o {
d.params[key] = urllib.query_escape(value.replace("'", '"')) d.params[key] = urllib.query_escape(value.replace("'", '"'))
@ -41,17 +41,11 @@ fn (mut d DockerConn) params[T](o T) {
} }
fn (mut d DockerConn) send() ! { fn (mut d DockerConn) send() ! {
mut full_url := '/${docker.api_version}${d.url}' mut full_url := d.url
if d.params.len > 0 { if d.params.len > 0 {
mut fields := []string{cap: d.params.len} params_str := d.params.keys().map('$it=${d.params[it]}').join('&')
full_url += '?$params_str'
for key, value in d.params {
fields << '${key}=${value}'
}
params_str := fields.join('&')
// params_str := d.params.keys().map('${it}=${d.params[it]}').join('&')
full_url += '?${params_str}'
} }
// This is to make sure we actually created a valid URL // This is to make sure we actually created a valid URL
@ -59,9 +53,9 @@ fn (mut d DockerConn) send() ! {
final_url := parsed_url.request_uri() final_url := parsed_url.request_uri()
req := if d.body == '' { req := if d.body == '' {
'${d.method} ${final_url} HTTP/1.1\nHost: localhost\n\n' '$d.method $final_url HTTP/1.1\nHost: localhost\n\n'
} else { } else {
'${d.method} ${final_url} HTTP/1.1\nHost: localhost\nContent-Type: ${d.content_type}\nContent-Length: ${d.body.len}\n\n${d.body}\n\n' '$d.method $final_url HTTP/1.1\nHost: localhost\nContent-Type: $d.content_type\nContent-Length: $d.body.len\n\n$d.body\n\n'
} }
d.socket.write_string(req)! d.socket.write_string(req)!

View File

@ -21,7 +21,7 @@ pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ! {
// match_array_in_array<T> returns how many elements of a2 overlap with a1. For // match_array_in_array<T> returns how many elements of a2 overlap with a1. For
// example, if a1 = "abcd" & a2 = "cd", the result will be 2. If the match is // example, if a1 = "abcd" & a2 = "cd", the result will be 2. If the match is
// not at the end of a1, the result is 0. // not at the end of a1, the result is 0.
pub fn match_array_in_array[T](a1 []T, a2 []T) int { pub fn match_array_in_array<T>(a1 []T, a2 []T) int {
mut i := 0 mut i := 0
mut match_len := 0 mut match_len := 0

View File

@ -20,7 +20,7 @@ pub fn (mut d DockerConn) volume_list() !VolumeListResponse {
d.request(.get, '/volumes') d.request(.get, '/volumes')
d.send()! d.send()!
mut data := d.read_json_response[VolumeListResponse]()! mut data := d.read_json_response<VolumeListResponse>()!
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)!