2022-05-07 15:10:07 +02:00
|
|
|
module server
|
|
|
|
|
|
|
|
import web
|
|
|
|
import net.http
|
|
|
|
import net.urllib
|
|
|
|
import response { new_data_response, new_response }
|
|
|
|
import db
|
|
|
|
import time
|
|
|
|
import os
|
|
|
|
import util
|
2022-05-29 20:08:21 +02:00
|
|
|
import models { BuildLog, BuildLogFilter }
|
2022-05-07 15:10:07 +02:00
|
|
|
|
2022-05-07 22:06:17 +02:00
|
|
|
// get_logs returns all build logs in the database. A 'repo' query param can
|
|
|
|
// optionally be added to limit the list of build logs to that repository.
|
2022-05-07 15:10:07 +02:00
|
|
|
['/api/logs'; get]
|
|
|
|
fn (mut app App) get_logs() web.Result {
|
|
|
|
if !app.is_authorized() {
|
|
|
|
return app.json(http.Status.unauthorized, new_response('Unauthorized.'))
|
|
|
|
}
|
|
|
|
|
2022-05-29 20:08:21 +02:00
|
|
|
filter := models.from_params<BuildLogFilter>(app.query) or {
|
|
|
|
return app.json(http.Status.bad_request, new_response('Invalid query parameters.'))
|
2022-05-07 15:31:01 +02:00
|
|
|
}
|
2022-05-29 20:08:21 +02:00
|
|
|
logs := app.db.get_build_logs(filter)
|
2022-05-07 15:10:07 +02:00
|
|
|
|
|
|
|
return app.json(http.Status.ok, new_data_response(logs))
|
|
|
|
}
|
|
|
|
|
2022-05-07 22:06:17 +02:00
|
|
|
// get_single_log returns the build log with the given id.
|
2022-05-07 15:41:49 +02:00
|
|
|
['/api/logs/:id'; get]
|
|
|
|
fn (mut app App) get_single_log(id int) web.Result {
|
|
|
|
if !app.is_authorized() {
|
|
|
|
return app.json(http.Status.unauthorized, new_response('Unauthorized.'))
|
|
|
|
}
|
2022-05-07 19:38:28 +02:00
|
|
|
|
2022-05-07 15:41:49 +02:00
|
|
|
log := app.db.get_build_log(id) or { return app.not_found() }
|
|
|
|
|
|
|
|
return app.json(http.Status.ok, new_data_response(log))
|
|
|
|
}
|
|
|
|
|
2022-05-07 22:06:17 +02:00
|
|
|
// get_log_content returns the actual build log file for the given id.
|
2022-05-07 15:41:49 +02:00
|
|
|
['/api/logs/:id/content'; get]
|
2022-05-07 22:06:17 +02:00
|
|
|
fn (mut app App) get_log_content(id int) web.Result {
|
2022-05-07 15:41:49 +02:00
|
|
|
if !app.is_authorized() {
|
|
|
|
return app.json(http.Status.unauthorized, new_response('Unauthorized.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
log := app.db.get_build_log(id) or { return app.not_found() }
|
|
|
|
file_name := log.start_time.custom_format('YYYY-MM-DD_HH-mm-ss')
|
2022-05-07 19:38:28 +02:00
|
|
|
full_path := os.join_path(app.conf.data_dir, logs_dir_name, log.repo_id.str(), log.arch,
|
|
|
|
file_name)
|
2022-05-07 15:41:49 +02:00
|
|
|
|
|
|
|
return app.file(full_path)
|
|
|
|
}
|
|
|
|
|
2022-05-07 15:10:07 +02:00
|
|
|
// parse_query_time unescapes an HTTP query parameter & tries to parse it as a
|
|
|
|
// time.Time struct.
|
|
|
|
fn parse_query_time(query string) ?time.Time {
|
2022-05-14 20:06:08 +02:00
|
|
|
unescaped := urllib.query_unescape(query)?
|
|
|
|
t := time.parse(unescaped)?
|
2022-05-07 15:10:07 +02:00
|
|
|
|
|
|
|
return t
|
|
|
|
}
|
|
|
|
|
2022-05-07 22:06:17 +02:00
|
|
|
// post_log adds a new log to the database.
|
2022-05-07 15:10:07 +02:00
|
|
|
['/api/logs'; post]
|
|
|
|
fn (mut app App) post_log() web.Result {
|
|
|
|
if !app.is_authorized() {
|
|
|
|
return app.json(http.Status.unauthorized, new_response('Unauthorized.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse query params
|
|
|
|
start_time := parse_query_time(app.query['startTime']) or {
|
|
|
|
return app.json(http.Status.bad_request, new_response('Invalid or missing start time.'))
|
|
|
|
}
|
|
|
|
|
2022-05-07 15:41:49 +02:00
|
|
|
end_time := parse_query_time(app.query['endTime']) or {
|
2022-05-07 15:10:07 +02:00
|
|
|
return app.json(http.Status.bad_request, new_response('Invalid or missing end time.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
if 'exitCode' !in app.query {
|
|
|
|
return app.json(http.Status.bad_request, new_response('Missing exit code.'))
|
|
|
|
}
|
|
|
|
|
|
|
|
exit_code := app.query['exitCode'].int()
|
|
|
|
|
|
|
|
if 'arch' !in app.query {
|
|
|
|
return app.json(http.Status.bad_request, new_response("Missing parameter 'arch'."))
|
|
|
|
}
|
|
|
|
|
|
|
|
arch := app.query['arch']
|
|
|
|
|
2022-05-07 15:44:59 +02:00
|
|
|
repo_id := app.query['repo'].int()
|
2022-05-07 15:31:01 +02:00
|
|
|
|
2022-05-07 15:44:59 +02:00
|
|
|
if !app.db.git_repo_exists(repo_id) {
|
|
|
|
return app.json(http.Status.bad_request, new_response('Unknown Git repo.'))
|
2022-05-07 15:10:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Store log in db
|
2022-05-19 08:20:11 +02:00
|
|
|
log := BuildLog{
|
2022-05-07 15:44:59 +02:00
|
|
|
repo_id: repo_id
|
2022-05-07 15:10:07 +02:00
|
|
|
start_time: start_time
|
|
|
|
end_time: end_time
|
2022-05-07 15:41:49 +02:00
|
|
|
arch: arch
|
2022-05-07 15:10:07 +02:00
|
|
|
exit_code: exit_code
|
|
|
|
}
|
|
|
|
|
|
|
|
app.db.add_build_log(log)
|
|
|
|
|
2022-05-07 15:44:59 +02:00
|
|
|
repo_logs_dir := os.join_path(app.conf.data_dir, logs_dir_name, repo_id.str(), arch)
|
2022-05-07 15:10:07 +02:00
|
|
|
|
|
|
|
// Create the logs directory of it doesn't exist
|
|
|
|
if !os.exists(repo_logs_dir) {
|
|
|
|
os.mkdir_all(repo_logs_dir) or {
|
|
|
|
app.lerror("Couldn't create dir '$repo_logs_dir'.")
|
|
|
|
|
|
|
|
return app.json(http.Status.internal_server_error, new_response('An error occured while processing the request.'))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Stream log contents to correct file
|
|
|
|
file_name := start_time.custom_format('YYYY-MM-DD_HH-mm-ss')
|
|
|
|
full_path := os.join_path_single(repo_logs_dir, file_name)
|
|
|
|
|
|
|
|
if length := app.req.header.get(.content_length) {
|
|
|
|
util.reader_to_file(mut app.reader, length.int(), full_path) or {
|
|
|
|
app.lerror('An error occured while receiving logs: $err.msg()')
|
|
|
|
|
|
|
|
return app.json(http.Status.internal_server_error, new_response('Failed to upload logs.'))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return app.status(http.Status.length_required)
|
|
|
|
}
|
|
|
|
|
|
|
|
return app.json(http.Status.ok, new_response('Logs added successfully.'))
|
|
|
|
}
|