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 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, | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -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' | ||||||
|  | @ -124,7 +129,7 @@ pub fn (mut d DockerDaemon) read_response() ?(http.Response, string) { | ||||||
| 		mut builder := strings.new_builder(1024) | 		mut builder := strings.new_builder(1024) | ||||||
| 		mut body := d.get_chunked_response_reader() | 		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() | 		return head, builder.str() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -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{ | ||||||
|  |  | ||||||
|  | @ -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 } | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue