diff options
Diffstat (limited to 'src/smd')
-rw-r--r-- | src/smd/context.rs | 27 | ||||
-rw-r--r-- | src/smd/endpoints.rs | 36 | ||||
-rw-r--r-- | src/smd/main.rs | 71 |
3 files changed, 110 insertions, 24 deletions
diff --git a/src/smd/context.rs b/src/smd/context.rs new file mode 100644 index 0000000..d8194c5 --- /dev/null +++ b/src/smd/context.rs @@ -0,0 +1,27 @@ +use super::Config; +use salaryman::service::Service; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use tokio::sync::Mutex; + +pub struct SalarymanDContext { + pub config: Config, + pub service: Vec<Arc<Mutex<Service>>>, +} +impl SalarymanDContext { + pub fn new() -> Self { + Self { + config: Config::new(), + service: Vec::new(), + } + } + pub fn from_parts(config: Config, service: Vec<Arc<Mutex<Service>>>) -> Self { + Self { config, service } + } +} + +#[derive(Serialize, Deserialize, JsonSchema, Debug)] +pub struct StdinBuffer { + pub string: String, +} diff --git a/src/smd/endpoints.rs b/src/smd/endpoints.rs index 8b13789..48c9720 100644 --- a/src/smd/endpoints.rs +++ b/src/smd/endpoints.rs @@ -1 +1,37 @@ +use super::{ + Config, + context::{SalarymanDContext, StdinBuffer}, +}; +use dropshot::{HttpError, HttpResponseOk, RequestContext, TypedBody, endpoint}; +use std::sync::Arc; +#[endpoint { + method = GET, + path = "/config", +}] +pub async fn endpoint_get_config( + rqctx: RequestContext<Arc<SalarymanDContext>>, +) -> Result<HttpResponseOk<Config>, HttpError> { + Ok(HttpResponseOk(rqctx.context().config.clone())) +} + +#[endpoint { + method = PUT, + path = "/services/write" +}] +pub async fn endpoint_post_stdin( + rqctx: RequestContext<Arc<SalarymanDContext>>, + update: TypedBody<StdinBuffer>, +) -> Result<HttpResponseOk<()>, HttpError> { + let ctx = rqctx.context(); + let stdin_str = update.into_inner(); + for i in 0..ctx.service.len() { + let mut lock = ctx.service[i].lock().await; + if lock.started().await { + lock.writeln_stdin(stdin_str.string.clone()).await.unwrap(); //TODO: PROPERLY HANDLE ERROR! + } + drop(lock); + } + + Ok(HttpResponseOk(())) +} diff --git a/src/smd/main.rs b/src/smd/main.rs index fee2d9e..628785a 100644 --- a/src/smd/main.rs +++ b/src/smd/main.rs @@ -1,11 +1,17 @@ +mod context; mod endpoints; use clap::Parser; +use dropshot::{ApiDescription, ConfigLogging, ConfigLoggingLevel, ServerBuilder}; use salaryman::service::{Service, ServiceConf}; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use tokio::fs::read_to_string; +use tokio::{fs::read_to_string, sync::Mutex}; -use std::{net::IpAddr, path::PathBuf}; +use std::{net::IpAddr, path::PathBuf, sync::Arc}; + +use crate::context::SalarymanDContext; +use crate::endpoints::{endpoint_get_config, endpoint_post_stdin}; #[derive(Parser, Debug)] #[command(version, about, long_about = None)] @@ -36,11 +42,28 @@ struct Args { port: u16, } -#[derive(Serialize, Deserialize, Debug)] -struct Config { - address: Option<IpAddr>, - port: Option<u16>, - service: Vec<ServiceConf>, +#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)] +pub struct User { + pub username: String, + pub token: String, +} + +#[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)] +pub struct Config { + pub address: Option<IpAddr>, + pub port: Option<u16>, + pub user: Vec<User>, + pub service: Vec<ServiceConf>, +} +impl Config { + pub fn new() -> Self { + Self { + address: None, + port: None, + user: Vec::new(), + service: Vec::new(), + } + } } async fn load_config(file: &PathBuf) -> Result<Config, Box<dyn std::error::Error>> { @@ -66,26 +89,26 @@ async fn load_config(file: &PathBuf) -> Result<Config, Box<dyn std::error::Error async fn main() -> Result<(), Box<dyn std::error::Error>> { let args = Args::parse(); let conf: Config = load_config(&args.config).await?; - let mut services: Vec<Service> = Vec::new(); + let mut services: Vec<Arc<Mutex<Service>>> = Vec::new(); for i in 0..conf.service.len() { - services.push(Service::from_conf(&conf.service[i])); + services.push(Arc::new(Mutex::new(Service::from_conf(&conf.service[i])))); if conf.service[i].autostart { - services[i].start().await?; - services[i].scan_stdout().await?; - services[i].scan_stderr().await?; - } - } - tokio::time::sleep(std::time::Duration::from_secs(60)).await; - println!("trying to write to stdin!"); - for i in 0..services.len() { - services[i].write_stdin("stop\n".into()).await?; - } - tokio::time::sleep(std::time::Duration::from_secs(30)).await; - for mut service in services { - match service.stop().await { - Ok(_) => println!("lol it was killed"), - Err(_) => println!("it either didn't exist, or failed to kill"), + let mut lock = services[i].lock().await; + lock.start().await?; + lock.scan_stdout().await?; + lock.scan_stderr().await?; + drop(lock); } } + let log_conf = ConfigLogging::StderrTerminal { + level: ConfigLoggingLevel::Info, + }; + let log = log_conf.to_logger("smd")?; + let ctx = Arc::new(SalarymanDContext::from_parts(conf, services)); + let mut api = ApiDescription::new(); + api.register(endpoint_get_config).unwrap(); + api.register(endpoint_post_stdin).unwrap(); + let server = ServerBuilder::new(api, ctx.clone(), log).start()?; + server.await?; Ok(()) } |