feat(docker): fully migrate build commands to new code

Jef Roosens 2022-05-15 09:56:23 +02:00
parent 79fd9c1f87
commit e041682fea
Signed by untrusted user: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 70 additions and 16 deletions

View File

@ -6,6 +6,8 @@ import time
import os import os
import db import db
import client import client
import strings
import util
const container_build_dir = '/build' const container_build_dir = '/build'
@ -19,6 +21,10 @@ const build_image_repo = 'vieter-build'
pub fn create_build_image(base_image string) ?string { pub fn create_build_image(base_image string) ?string {
mut dd := docker.new_conn()? mut dd := docker.new_conn()?
defer {
dd.close() or {}
}
commands := [ commands := [
// Update repos & install required packages // Update repos & install required packages
'pacman -Syu --needed --noconfirm base-devel git' 'pacman -Syu --needed --noconfirm base-devel git'
@ -48,7 +54,7 @@ pub fn create_build_image(base_image string) ?string {
image_tag := if image_parts.len > 1 { image_parts[1] } else { 'latest' } image_tag := if image_parts.len > 1 { image_parts[1] } else { 'latest' }
// We pull the provided image // We pull the provided image
docker.pull_image(image_name, image_tag)? dd.pull_image(image_name, image_tag)?
id := dd.create_container(c)?.id id := dd.create_container(c)?.id
// id := docker.create_container(c)? // id := docker.create_container(c)?
@ -70,7 +76,7 @@ pub fn create_build_image(base_image string) ?string {
// TODO also add the base image's name into the image name to prevent // TODO also add the base image's name into the image name to prevent
// conflicts. // conflicts.
tag := time.sys_mono_now().str() tag := time.sys_mono_now().str()
image := docker.create_image_from_container(id, 'vieter-build', tag)? image := dd.create_image_from_container(id, 'vieter-build', tag)?
dd.remove_container(id)? dd.remove_container(id)?
return image.id return image.id
@ -88,6 +94,12 @@ pub:
// provided GitRepo. The base image ID should be of an image previously created // provided GitRepo. The base image ID should be of an image previously created
// by create_build_image. It returns the logs of the container. // by create_build_image. It returns the logs of the container.
pub fn build_repo(address string, api_key string, base_image_id string, repo &db.GitRepo) ?BuildResult { pub fn build_repo(address string, api_key string, base_image_id string, repo &db.GitRepo) ?BuildResult {
mut dd := docker.new_conn()?
defer {
dd.close() or {}
}
build_arch := os.uname().machine build_arch := os.uname().machine
// TODO what to do with PKGBUILDs that build multiple packages? // TODO what to do with PKGBUILDs that build multiple packages?
@ -115,27 +127,31 @@ pub fn build_repo(address string, api_key string, base_image_id string, repo &db
user: 'builder:builder' user: 'builder:builder'
} }
id := docker.create_container(c)? id := dd.create_container(c)?.id
docker.start_container(id)? dd.start_container(id)?
mut data := docker.inspect_container(id)? mut data := dd.inspect_container(id)?
// This loop waits until the container has stopped, so we can remove it after // This loop waits until the container has stopped, so we can remove it after
for data.state.running { for data.state.running {
time.sleep(1 * time.second) time.sleep(1 * time.second)
data = docker.inspect_container(id)? data = dd.inspect_container(id)?
} }
logs := docker.get_container_logs(id)? mut logs_stream := dd.get_container_logs(id)?
docker.remove_container(id)? // Read in the entire stream
mut logs_builder := strings.new_builder(10 * 1024)
util.reader_to_writer(mut logs_stream, mut logs_builder)?
dd.remove_container(id)?
return BuildResult{ return BuildResult{
start_time: data.state.start_time start_time: data.state.start_time
end_time: data.state.end_time end_time: data.state.end_time
exit_code: data.state.exit_code exit_code: data.state.exit_code
logs: logs logs: logs_builder.str()
} }
} }
@ -153,7 +169,14 @@ fn build(conf Config, repo_id int) ? {
res := build_repo(conf.address, conf.api_key, image_id, repo)? res := build_repo(conf.address, conf.api_key, image_id, repo)?
println('Removing build image...') println('Removing build image...')
docker.remove_image(image_id)?
mut dd := docker.new_conn()?
defer {
dd.close() or {}
}
dd.remove_image(image_id)?
println('Uploading logs to Vieter...') println('Uploading logs to Vieter...')
c.add_build_log(repo.id, res.start_time, res.end_time, build_arch, res.exit_code, c.add_build_log(repo.id, res.start_time, res.end_time, build_arch, res.exit_code,

View File

@ -22,14 +22,13 @@ pub fn (mut d DockerDaemon) pull_image(image string, tag string) ? {
return error(data.message) return error(data.message)
} }
// Keep reading the body until the pull has completed
mut body := d.get_chunked_response_reader() mut body := d.get_chunked_response_reader()
mut buf := []u8{len: 1024} mut buf := []u8{len: 1024}
for { for {
c := body.read(mut buf) or { break } body.read(mut buf) or { break }
print(buf[..c].bytestr())
} }
} }
@ -38,6 +37,22 @@ pub fn pull_image(image string, tag string) ?http.Response {
return request('POST', urllib.parse('/v1.41/images/create?fromImage=$image&tag=$tag')?) return request('POST', urllib.parse('/v1.41/images/create?fromImage=$image&tag=$tag')?)
} }
// create_image_from_container creates a new image from a container.
pub fn (mut d DockerDaemon) create_image_from_container(id string, repo string, tag string) ?Image {
d.send_request('POST', urllib.parse('/v1.41/commit?container=$id&repo=$repo&tag=$tag')?)?
head, body := d.read_response()?
if head.status_code != 201 {
data := json.decode(DockerError, body)?
return error(data.message)
}
data := json.decode(Image, body)?
return data
}
// create_image_from_container creates a new image from a container with the // create_image_from_container creates a new image from a container with the
// given repo & tag, given the container's ID. // given repo & tag, given the container's ID.
pub fn create_image_from_container(id string, repo string, tag string) ?Image { pub fn create_image_from_container(id string, repo string, tag string) ?Image {
@ -56,3 +71,15 @@ pub fn remove_image(id string) ?bool {
return res.status_code == 200 return res.status_code == 200
} }
// remove_image removes the image with the given id.
pub fn (mut d DockerDaemon) remove_image(id string) ? {
d.send_request('DELETE', urllib.parse('/v1.41/images/$id')?)?
head, body := d.read_response()?
if head.status_code != 200 {
data := json.decode(DockerError, body)?
return error(data.message)
}
}

View File

@ -33,6 +33,11 @@ pub fn new_conn() ?&DockerDaemon {
return d return d
} }
// close closes the underlying socket connection.
pub fn (mut d DockerDaemon) close() ? {
d.socket.close()?
}
// send_request sends an HTTP request without body. // send_request sends an HTTP request without body.
pub fn (mut d DockerDaemon) send_request(method string, url urllib.URL) ? { pub fn (mut d DockerDaemon) send_request(method string, url urllib.URL) ? {
req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n' req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n'

View File

@ -7,7 +7,6 @@ import build
import console.git import console.git
import console.logs import console.logs
import cron import cron
import docker
fn main() { fn main() {
mut app := cli.Command{ mut app := cli.Command{

View File

@ -28,7 +28,7 @@ pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ? {
mut buf := []u8{len: 10 * 1024} mut buf := []u8{len: 10 * 1024}
for { for {
c := reader.read(mut buf) or { break } reader.read(mut buf) or { break }
writer.write(buf) or { break } writer.write(buf) or { break }
} }