From 1a99cfd1a25397ec36c7c6053788799feaa4448a Mon Sep 17 00:00:00 2001 From: fluo10 Date: Sun, 1 Jun 2025 16:29:35 +0900 Subject: [PATCH] Implement init config command --- lazy-supplements/src/cli/init.rs | 19 +++++--- lazy-supplements/src/cli/mod.rs | 5 +-- lazy-supplements/src/cli/node.rs | 10 ++--- lazy-supplements/src/config/mod.rs | 2 +- lazy-supplements/src/config/node.rs | 62 +++++++++++++++++++++++++-- lazy-supplements/src/config/server.rs | 54 ----------------------- lazy-supplements/src/main.rs | 26 +++++++++++ 7 files changed, 105 insertions(+), 73 deletions(-) delete mode 100644 lazy-supplements/src/config/server.rs create mode 100644 lazy-supplements/src/main.rs diff --git a/lazy-supplements/src/cli/init.rs b/lazy-supplements/src/cli/init.rs index e80283e..5e6fcc7 100644 --- a/lazy-supplements/src/cli/init.rs +++ b/lazy-supplements/src/cli/init.rs @@ -3,26 +3,31 @@ use std::path::PathBuf; use clap::Args; use libp2p::identity; +use crate::{config::RawNodeConfig, global::DEFAULT_CONFIG_FILE_PATH}; + #[derive(Args, Debug)] pub struct InitArgs { #[arg(long)] - config: Option + config: Option, + #[arg(short, long)] + force: bool, + #[command(flatten)] + node_config: RawNodeConfig, } impl InitArgs { - fn main(self) { + pub async fn init_config(self) { let config_path = if let Some(x) = self.config { x } else { - crate::cli::default_config_path() + DEFAULT_CONFIG_FILE_PATH.to_path_buf() }; - if config_path.exists() { + if config_path.exists() && !self.force { println!("Config file already exists!"); return; } else { - let keypair = identity::Keypair::generate_ed25519(); - let buf = keypair.to_protobuf_encoding().unwrap(); - + let config = self.node_config.with_new_secret(); + config.write_to(config_path).await.unwrap() } } diff --git a/lazy-supplements/src/cli/mod.rs b/lazy-supplements/src/cli/mod.rs index 9fd7c8e..e13fdab 100644 --- a/lazy-supplements/src/cli/mod.rs +++ b/lazy-supplements/src/cli/mod.rs @@ -3,6 +3,5 @@ use std::path::PathBuf; mod init; mod node; -pub fn default_config_path() -> PathBuf { - todo!() -} \ No newline at end of file +pub use init::InitArgs; +pub use node::{ NodeArgs, NodeCommand, JoinNodeArgs }; diff --git a/lazy-supplements/src/cli/node.rs b/lazy-supplements/src/cli/node.rs index 16d1567..5b526d3 100644 --- a/lazy-supplements/src/cli/node.rs +++ b/lazy-supplements/src/cli/node.rs @@ -12,19 +12,19 @@ use crate::error::Error; #[derive(Args, Debug)] pub struct NodeArgs { #[command(subcommand)] - command: NodeCommand + pub command: NodeCommand } #[derive(Args, Debug)] pub struct JoinNodeArgs { #[arg(long)] - endpoint: IpAddr, + pub endpoint: IpAddr, #[arg(long)] - port: u16, + pub port: u16, #[arg(long)] - peer_id: String, + pub peer_id: String, #[arg(long)] - config: Option, + pub config: Option, } #[derive(Debug, Subcommand)] diff --git a/lazy-supplements/src/config/mod.rs b/lazy-supplements/src/config/mod.rs index 14f1c7d..a4b069f 100644 --- a/lazy-supplements/src/config/mod.rs +++ b/lazy-supplements/src/config/mod.rs @@ -2,7 +2,7 @@ mod node; use std::path::Path; use crate::error::Error; -pub use node::NodeConfig; +pub use node::{ NodeConfig, RawNodeConfig }; use serde::{Deserialize, Serialize}; pub use crate::global::{ DEFAULT_LISTEN_IPS, diff --git a/lazy-supplements/src/config/node.rs b/lazy-supplements/src/config/node.rs index c15a9ab..05afa95 100644 --- a/lazy-supplements/src/config/node.rs +++ b/lazy-supplements/src/config/node.rs @@ -1,13 +1,15 @@ -use std::{net::IpAddr, path::PathBuf}; +use std::{net::IpAddr, path::{Path, PathBuf}}; use base64::{prelude::BASE64_STANDARD, Engine}; +use clap::Args; use libp2p::identity::{self, DecodingError, Keypair}; use serde::{Deserialize, Serialize}; +use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}}; use crate::{error::Error, global::DEFAULT_DATABASE_FILE_PATH}; -use super::{DEFAULT_LISTEN_IPS, DEFAULT_PORT}; +use super::{PartialConfig, DEFAULT_LISTEN_IPS, DEFAULT_PORT}; fn keypair_to_base64(keypair: &Keypair) -> Result { let vec = keypair.to_protobuf_encoding()?; @@ -76,13 +78,67 @@ mod keypair_parser { } } -#[derive(Debug, Deserialize, Serialize)] +#[derive(Args, Debug, Deserialize, Serialize)] pub struct RawNodeConfig { + #[arg(skip)] secret: Option, + #[arg(long)] database_path: Option, + #[arg(long)] listen_ips: Option>, + #[arg(long)] port: Option, } +impl RawNodeConfig { + + pub fn with_new_secret(mut self) -> Self { + self.secret = Some(keypair_to_base64(&Keypair::generate_ed25519()).unwrap()); + self + } + + pub fn new() -> Self { + RawNodeConfig { + secret: None, + database_path: None, + listen_ips: None, + port: None, + } + } + + pub async fn read_or_create(path: T) -> Result + where + T: AsRef + { + if !path.as_ref().exists() { + Self::new().write_to(&path).await?; + } + Self::read_from(&path).await + } + pub async fn read_from(path:T) -> Result + where + T: AsRef + { + let mut file = File::open(path.as_ref()).await?; + let mut content = String::new(); + file.read_to_string(&mut content).await?; + let config: RawNodeConfig = toml::from_str(&content)?; + Ok(config) + } + pub async fn write_to(&self, path:T) -> Result<(), Error> + where + T: AsRef + { + if !path.as_ref().exists() { + if let Some(x) = path.as_ref().parent() { + std::fs::create_dir_all(x)?; + }; + let _ = File::create(&path).await?; + } + let mut file = File::create(&path).await?; + file.write_all(toml::to_string(self)?.as_bytes()).await?; + Ok(()) + } +} #[cfg(test)] mod tests { diff --git a/lazy-supplements/src/config/server.rs b/lazy-supplements/src/config/server.rs deleted file mode 100644 index 2805d57..0000000 --- a/lazy-supplements/src/config/server.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::{collections::HashSet, net::{IpAddr, Ipv4Addr}, str::FromStr, sync::LazyLock}; - -use clap::Args; -use serde::{Deserialize, Serialize}; - -use crate::error::Error; - -pub static DEFAULT_LISTEN_IPS: &[IpAddr] = &[IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))]; -pub static DEFAULT_PORT: u16 = 8080; -pub static DEFAULT_SERVER_CONFIG: LazyLock = LazyLock::new(|| { - ServerConfig{ - listen_ips: Vec::from(DEFAULT_LISTEN_IPS), - port: DEFAULT_PORT - } -}); -pub static DEFAULT_PARTIAL_SERVER_CONFIG: LazyLock = LazyLock::new(|| { - PartialServerConfig::from((*DEFAULT_SERVER_CONFIG).clone()) -}); - -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct ServerConfig { - listen_ips: Vec, - port: u16, -} - -impl TryFrom for ServerConfig { - type Error = Error; - fn try_from(config: PartialServerConfig) -> Result{ - Ok(ServerConfig { - listen_ips: config.listen_ips.ok_or(Error::MissingConfig("listen_ips".to_string()))?, - port: config.port.ok_or(Error::MissingConfig("port".to_string()))? - }) - } -} - -#[derive(Args, Debug, Deserialize, Serialize)] -pub struct PartialServerConfig { - #[arg(long)] - listen_ips: Option>, - #[arg(long)] - port: Option, -} - -impl From for PartialServerConfig { - fn from(config: ServerConfig) -> PartialServerConfig { - PartialServerConfig { - listen_ips: Some(config.listen_ips), - port: Some(config.port) - } - } -} - - - diff --git a/lazy-supplements/src/main.rs b/lazy-supplements/src/main.rs new file mode 100644 index 0000000..346538b --- /dev/null +++ b/lazy-supplements/src/main.rs @@ -0,0 +1,26 @@ +use clap::{Parser, Subcommand}; +use lazy_supplements::{cli::{InitArgs, NodeArgs, NodeCommand}, *}; + +#[derive(Debug, Parser)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Subcommand)] +enum Command { + Node(NodeArgs), + Init(InitArgs), +} + + +#[tokio::main] +async fn main() { + match Cli::parse().command { + Command::Node(x) => match x.command { + NodeCommand::Ping(y) => y.ping().await.unwrap(), + NodeCommand::Join(y) => println!("{y:?}"), + }, + Command::Init(x) => x.init_config().await, + } +} \ No newline at end of file