forked from vieter-v/vieter
				
			feat(docker): fully migrate build commands to new code
							parent
							
								
									79fd9c1f87
								
							
						
					
					
						commit
						e041682fea
					
				| 
						 | 
				
			
			@ -6,6 +6,8 @@ import time
 | 
			
		|||
import os
 | 
			
		||||
import db
 | 
			
		||||
import client
 | 
			
		||||
import strings
 | 
			
		||||
import util
 | 
			
		||||
 | 
			
		||||
const container_build_dir = '/build'
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +21,10 @@ const build_image_repo = 'vieter-build'
 | 
			
		|||
pub fn create_build_image(base_image string) ?string {
 | 
			
		||||
	mut dd := docker.new_conn()?
 | 
			
		||||
 | 
			
		||||
	defer {
 | 
			
		||||
		dd.close() or {}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commands := [
 | 
			
		||||
		// Update repos & install required packages
 | 
			
		||||
		'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' }
 | 
			
		||||
 | 
			
		||||
	// 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 := 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
 | 
			
		||||
	// conflicts.
 | 
			
		||||
	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)?
 | 
			
		||||
 | 
			
		||||
	return image.id
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +94,12 @@ pub:
 | 
			
		|||
// provided GitRepo. The base image ID should be of an image previously created
 | 
			
		||||
// 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 {
 | 
			
		||||
	mut dd := docker.new_conn()?
 | 
			
		||||
 | 
			
		||||
	defer {
 | 
			
		||||
		dd.close() or {}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	build_arch := os.uname().machine
 | 
			
		||||
 | 
			
		||||
	// 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'
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	id := docker.create_container(c)?
 | 
			
		||||
	docker.start_container(id)?
 | 
			
		||||
	id := dd.create_container(c)?.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
 | 
			
		||||
	for data.state.running {
 | 
			
		||||
		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{
 | 
			
		||||
		start_time: data.state.start_time
 | 
			
		||||
		end_time: data.state.end_time
 | 
			
		||||
		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)?
 | 
			
		||||
 | 
			
		||||
	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...')
 | 
			
		||||
	c.add_build_log(repo.id, res.start_time, res.end_time, build_arch, res.exit_code,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,14 +22,13 @@ pub fn (mut d DockerDaemon) pull_image(image string, tag string) ? {
 | 
			
		|||
		return error(data.message)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Keep reading the body until the pull has completed
 | 
			
		||||
	mut body := d.get_chunked_response_reader()
 | 
			
		||||
 | 
			
		||||
	mut buf := []u8{len: 1024}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		c := body.read(mut buf) or { break }
 | 
			
		||||
 | 
			
		||||
		print(buf[..c].bytestr())
 | 
			
		||||
		body.read(mut buf) or { break }
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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')?)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
// given repo & tag, given the container's ID.
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,11 @@ pub fn new_conn() ?&DockerDaemon {
 | 
			
		|||
	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.
 | 
			
		||||
pub fn (mut d DockerDaemon) send_request(method string, url urllib.URL) ? {
 | 
			
		||||
	req := '$method $url.request_uri() HTTP/1.1\nHost: localhost\n\n'
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +129,7 @@ pub fn (mut d DockerDaemon) read_response() ?(http.Response, string) {
 | 
			
		|||
		mut builder := strings.new_builder(1024)
 | 
			
		||||
		mut body := d.get_chunked_response_reader()
 | 
			
		||||
 | 
			
		||||
		util.reader_to_writer(mut body, mut builder) ?
 | 
			
		||||
		util.reader_to_writer(mut body, mut builder)?
 | 
			
		||||
 | 
			
		||||
		return head, builder.str()
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ import build
 | 
			
		|||
import console.git
 | 
			
		||||
import console.logs
 | 
			
		||||
import cron
 | 
			
		||||
import docker
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
	mut app := cli.Command{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ pub fn reader_to_writer(mut reader io.Reader, mut writer io.Writer) ? {
 | 
			
		|||
	mut buf := []u8{len: 10 * 1024}
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		c := reader.read(mut buf) or { break }
 | 
			
		||||
		reader.read(mut buf) or { break }
 | 
			
		||||
 | 
			
		||||
		writer.write(buf) or { break }
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue