ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/salaryman/trunk/src/smd/main.rs
Revision: 13
Committed: Wed Jul 9 20:24:36 2025 UTC (3 months ago) by yuzu
File size: 3182 byte(s)
Log Message:
working network communication

File Contents

# Content
1 mod context;
2 mod endpoints;
3
4 use clap::Parser;
5 use dropshot::{ApiDescription, ConfigLogging, ConfigLoggingLevel, ServerBuilder};
6 use salaryman::service::{Service, ServiceConf};
7 use schemars::JsonSchema;
8 use serde::{Deserialize, Serialize};
9 use tokio::{fs::read_to_string, sync::Mutex};
10
11 use std::{net::IpAddr, path::PathBuf, sync::Arc};
12
13 use crate::context::SalarymanDContext;
14 use crate::endpoints::{endpoint_get_config, endpoint_post_stdin};
15
16 #[derive(Parser, Debug)]
17 #[command(version, about, long_about = None)]
18 struct Args {
19 #[arg(
20 short,
21 long,
22 value_name = "FILE",
23 help = "config file override",
24 default_value = "salaryman.toml"
25 )]
26 config: PathBuf,
27 #[arg(
28 short,
29 long,
30 value_name = "ADDR",
31 help = "IP address to bind API to",
32 default_value = "127.0.0.1"
33 )]
34 address: IpAddr,
35 #[arg(
36 short,
37 long,
38 value_name = "PORT",
39 help = "TCP Port to bind API to",
40 default_value = "3080"
41 )]
42 port: u16,
43 }
44
45 #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
46 pub struct User {
47 pub username: String,
48 pub token: String,
49 }
50
51 #[derive(Serialize, Deserialize, JsonSchema, Clone, Debug)]
52 pub struct Config {
53 pub address: Option<IpAddr>,
54 pub port: Option<u16>,
55 pub user: Vec<User>,
56 pub service: Vec<ServiceConf>,
57 }
58 impl Config {
59 pub fn new() -> Self {
60 Self {
61 address: None,
62 port: None,
63 user: Vec::new(),
64 service: Vec::new(),
65 }
66 }
67 }
68
69 async fn load_config(file: &PathBuf) -> Result<Config, Box<dyn std::error::Error>> {
70 let s: String = match read_to_string(file).await {
71 Ok(s) => s,
72 Err(_) => {
73 return Err(Box::new(std::io::Error::new(
74 std::io::ErrorKind::NotFound,
75 "cannot find config file",
76 )));
77 }
78 };
79 match toml::from_str(s.as_str()) {
80 Ok(c) => Ok(c),
81 Err(_) => Err(Box::new(std::io::Error::new(
82 std::io::ErrorKind::Other,
83 "unable to parse config file",
84 ))),
85 }
86 }
87
88 #[tokio::main]
89 async fn main() -> Result<(), Box<dyn std::error::Error>> {
90 let args = Args::parse();
91 let conf: Config = load_config(&args.config).await?;
92 let mut services: Vec<Arc<Mutex<Service>>> = Vec::new();
93 for i in 0..conf.service.len() {
94 services.push(Arc::new(Mutex::new(Service::from_conf(&conf.service[i]))));
95 if conf.service[i].autostart {
96 let mut lock = services[i].lock().await;
97 lock.start().await?;
98 lock.scan_stdout().await?;
99 lock.scan_stderr().await?;
100 drop(lock);
101 }
102 }
103 let log_conf = ConfigLogging::StderrTerminal {
104 level: ConfigLoggingLevel::Info,
105 };
106 let log = log_conf.to_logger("smd")?;
107 let ctx = Arc::new(SalarymanDContext::from_parts(conf, services));
108 let mut api = ApiDescription::new();
109 api.register(endpoint_get_config).unwrap();
110 api.register(endpoint_post_stdin).unwrap();
111 let server = ServerBuilder::new(api, ctx.clone(), log).start()?;
112 server.await?;
113 Ok(())
114 }