From 909585a251b2ca4d3a11a7debe4ab36bf048b255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romaric=20Philog=C3=A8ne?= Date: Sat, 27 Apr 2024 17:27:34 +0200 Subject: [PATCH] wip(backend): add endpoint /selfServiceSectionsRuns/:slug/logs --- backend/src/database.rs | 8 ++++++++ backend/src/main.rs | 3 ++- backend/src/self_service/controllers.rs | 27 ++++++++++++++++++++++++- backend/src/self_service/mod.rs | 6 +++--- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/backend/src/database.rs b/backend/src/database.rs index e119324..048a470 100644 --- a/backend/src/database.rs +++ b/backend/src/database.rs @@ -93,6 +93,14 @@ pub struct SelfServiceRunJson { pub tasks: serde_json::Value, } +#[derive(Serialize, Deserialize, Debug)] +pub struct SelfServiceRunLogJson { + pub id: String, + pub created_at: String, + pub is_stderr: bool, + pub message: String, +} + /// Initialize the database by creating the tables pub async fn init_database(pg_pool: &Pool) -> Result<(), QError> { // execute SQL schema diff --git a/backend/src/main.rs b/backend/src/main.rs index 15c2a04..f6c5a9d 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -15,7 +15,7 @@ use tracing_subscriber::util::SubscriberInitExt; use crate::cli::CLI; use crate::database::init_database; -use crate::self_service::controllers::{exec_self_service_section_action_post_validate_scripts, exec_self_service_section_action_validate_scripts, list_self_service_section_actions, list_self_service_section_runs, list_self_service_section_runs_by_section_and_action_slugs, list_self_service_section_runs_by_section_slug, list_self_service_sections}; +use crate::self_service::controllers::{exec_self_service_section_action_post_validate_scripts, exec_self_service_section_action_validate_scripts, list_self_service_section_actions, list_self_service_section_run_logs, list_self_service_section_runs, list_self_service_section_runs_by_section_and_action_slugs, list_self_service_section_runs_by_section_slug, list_self_service_sections}; use crate::self_service::services::BackgroundWorkerTask; use crate::yaml_config::YamlConfig; @@ -110,6 +110,7 @@ async fn main() { .route("/healthz", get(|| async { "OK" })) .route("/selfServiceSections", get(list_self_service_sections)) .route("/selfServiceSections/runs", get(list_self_service_section_runs)) + .route("/selfServiceSectionsRuns/:slug/logs", get(list_self_service_section_run_logs)) .route("/selfServiceSections/:slug/actions", get(list_self_service_section_actions)) .route("/selfServiceSections/:slug/runs", get(list_self_service_section_runs_by_section_slug)) .route("/selfServiceSections/:slug/actions/:slug/validate", post(exec_self_service_section_action_validate_scripts)) diff --git a/backend/src/self_service/controllers.rs b/backend/src/self_service/controllers.rs index 33760e9..5eac44e 100644 --- a/backend/src/self_service/controllers.rs +++ b/backend/src/self_service/controllers.rs @@ -3,11 +3,12 @@ use std::sync::Arc; use axum::{debug_handler, Extension, Json}; use axum::extract::Path; use axum::http::StatusCode; +use chrono::{NaiveDateTime, Utc}; use tokio::sync::mpsc::Sender; use tracing::error; use crate::database; -use crate::database::{insert_self_service_run, SelfServiceRunJson, Status}; +use crate::database::{insert_self_service_run, SelfServiceRunJson, SelfServiceRunLogJson, Status}; use crate::self_service::{check_json_payload_against_yaml_config_fields, execute_command, ExecValidateScriptRequest, find_self_service_section_by_slug, get_self_service_section_and_action, JobResponse, ResultsResponse}; use crate::self_service::services::BackgroundWorkerTask; use crate::yaml_config::{SelfServiceSectionActionYamlConfig, SelfServiceSectionYamlConfig, YamlConfig}; @@ -82,6 +83,30 @@ pub async fn list_self_service_section_runs( } } +#[debug_handler] +pub async fn list_self_service_section_run_logs( + Extension(pg_pool): Extension>, + Path(logs_slug): Path, +) -> (StatusCode, Json>) { + + // mock data for now + let mut data = vec![]; + + for i in 1..1000 { + data.push(SelfServiceRunLogJson { + id: i.to_string(), + created_at: "2021-08-01T00:00:00Z".to_string(), + is_stderr: i % 2 == 0, + message: if i % 2 == 0 { format!("this is an error message {}", i) } else { format!("this is a log message {}", i) }, + }); + } + + (StatusCode::OK, Json(ResultsResponse { + message: None, + results: data, + })) +} + #[debug_handler] pub async fn exec_self_service_section_action_validate_scripts( Extension(yaml_config): Extension>, diff --git a/backend/src/self_service/mod.rs b/backend/src/self_service/mod.rs index f020758..09baa86 100644 --- a/backend/src/self_service/mod.rs +++ b/backend/src/self_service/mod.rs @@ -109,7 +109,7 @@ async fn execute_command( if external_command.get_command().len() == 1 { return Err(format!("Validate script '{}' is invalid. \ - Be explicit on the command to execute, e.g. 'python3 examples/validation_script.py'", + Be explicit on the command to execute, e.g. 'python examples/validation_script.py'", external_command.get_command()[0])); } @@ -129,6 +129,8 @@ async fn execute_command( Err(err) => return Err(format!("Validate script '{}' failed: {}", &cmd_one_line, err)) }; + // get stdout and stderr from child and forward it in real time to the upper function + let exit_status = match timeout(Duration::from_secs(external_command.get_timeout()), child.wait()).await { Ok(exit_status) => exit_status, Err(_) => return Err(match child.kill().await { @@ -148,8 +150,6 @@ async fn execute_command( return Err(format!("Validate script '{}' failed: {:?}", &cmd_one_line, exit_status)); } - // TODO parse output.stdout and output.stderr and forward to the frontend - Ok(consume_job_output_result_from_json_output_env(cmd_one_line.as_str(), start.elapsed().as_millis())) }