Implement init config command
This commit is contained in:
parent
8aa96d091a
commit
1a99cfd1a2
7 changed files with 105 additions and 73 deletions
|
@ -3,26 +3,31 @@ use std::path::PathBuf;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use libp2p::identity;
|
use libp2p::identity;
|
||||||
|
|
||||||
|
use crate::{config::RawNodeConfig, global::DEFAULT_CONFIG_FILE_PATH};
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct InitArgs {
|
pub struct InitArgs {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
config: Option<PathBuf>
|
config: Option<PathBuf>,
|
||||||
|
#[arg(short, long)]
|
||||||
|
force: bool,
|
||||||
|
#[command(flatten)]
|
||||||
|
node_config: RawNodeConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InitArgs {
|
impl InitArgs {
|
||||||
fn main(self) {
|
pub async fn init_config(self) {
|
||||||
let config_path = if let Some(x) = self.config {
|
let config_path = if let Some(x) = self.config {
|
||||||
x
|
x
|
||||||
} else {
|
} 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!");
|
println!("Config file already exists!");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
let keypair = identity::Keypair::generate_ed25519();
|
let config = self.node_config.with_new_secret();
|
||||||
let buf = keypair.to_protobuf_encoding().unwrap();
|
config.write_to(config_path).await.unwrap()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,5 @@ use std::path::PathBuf;
|
||||||
mod init;
|
mod init;
|
||||||
mod node;
|
mod node;
|
||||||
|
|
||||||
pub fn default_config_path() -> PathBuf {
|
pub use init::InitArgs;
|
||||||
todo!()
|
pub use node::{ NodeArgs, NodeCommand, JoinNodeArgs };
|
||||||
}
|
|
||||||
|
|
|
@ -12,19 +12,19 @@ use crate::error::Error;
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct NodeArgs {
|
pub struct NodeArgs {
|
||||||
#[command(subcommand)]
|
#[command(subcommand)]
|
||||||
command: NodeCommand
|
pub command: NodeCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct JoinNodeArgs {
|
pub struct JoinNodeArgs {
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
endpoint: IpAddr,
|
pub endpoint: IpAddr,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
port: u16,
|
pub port: u16,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
peer_id: String,
|
pub peer_id: String,
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
config: Option<PathBuf>,
|
pub config: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
|
|
|
@ -2,7 +2,7 @@ mod node;
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
pub use node::NodeConfig;
|
pub use node::{ NodeConfig, RawNodeConfig };
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use crate::global::{
|
pub use crate::global::{
|
||||||
DEFAULT_LISTEN_IPS,
|
DEFAULT_LISTEN_IPS,
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
use std::{net::IpAddr, path::PathBuf};
|
use std::{net::IpAddr, path::{Path, PathBuf}};
|
||||||
|
|
||||||
use base64::{prelude::BASE64_STANDARD, Engine};
|
use base64::{prelude::BASE64_STANDARD, Engine};
|
||||||
|
use clap::Args;
|
||||||
use libp2p::identity::{self, DecodingError, Keypair};
|
use libp2p::identity::{self, DecodingError, Keypair};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt}};
|
||||||
|
|
||||||
|
|
||||||
use crate::{error::Error, global::DEFAULT_DATABASE_FILE_PATH};
|
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<String, Error> {
|
fn keypair_to_base64(keypair: &Keypair) -> Result<String, Error> {
|
||||||
let vec = keypair.to_protobuf_encoding()?;
|
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 {
|
pub struct RawNodeConfig {
|
||||||
|
#[arg(skip)]
|
||||||
secret: Option<String>,
|
secret: Option<String>,
|
||||||
|
#[arg(long)]
|
||||||
database_path: Option<PathBuf>,
|
database_path: Option<PathBuf>,
|
||||||
|
#[arg(long)]
|
||||||
listen_ips: Option<Vec<IpAddr>>,
|
listen_ips: Option<Vec<IpAddr>>,
|
||||||
|
#[arg(long)]
|
||||||
port: Option<u16>,
|
port: Option<u16>,
|
||||||
}
|
}
|
||||||
|
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<T>(path: T) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
T: AsRef<Path>
|
||||||
|
{
|
||||||
|
if !path.as_ref().exists() {
|
||||||
|
Self::new().write_to(&path).await?;
|
||||||
|
}
|
||||||
|
Self::read_from(&path).await
|
||||||
|
}
|
||||||
|
pub async fn read_from<T>(path:T) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
T: AsRef<Path>
|
||||||
|
{
|
||||||
|
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<T>(&self, path:T) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
T: AsRef<Path>
|
||||||
|
{
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -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<ServerConfig> = LazyLock::new(|| {
|
|
||||||
ServerConfig{
|
|
||||||
listen_ips: Vec::from(DEFAULT_LISTEN_IPS),
|
|
||||||
port: DEFAULT_PORT
|
|
||||||
}
|
|
||||||
});
|
|
||||||
pub static DEFAULT_PARTIAL_SERVER_CONFIG: LazyLock<PartialServerConfig> = LazyLock::new(|| {
|
|
||||||
PartialServerConfig::from((*DEFAULT_SERVER_CONFIG).clone())
|
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct ServerConfig {
|
|
||||||
listen_ips: Vec<IpAddr>,
|
|
||||||
port: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<PartialServerConfig> for ServerConfig {
|
|
||||||
type Error = Error;
|
|
||||||
fn try_from(config: PartialServerConfig) -> Result<ServerConfig, Self::Error>{
|
|
||||||
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<Vec<IpAddr>>,
|
|
||||||
#[arg(long)]
|
|
||||||
port: Option<u16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ServerConfig> for PartialServerConfig {
|
|
||||||
fn from(config: ServerConfig) -> PartialServerConfig {
|
|
||||||
PartialServerConfig {
|
|
||||||
listen_ips: Some(config.listen_ips),
|
|
||||||
port: Some(config.port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
26
lazy-supplements/src/main.rs
Normal file
26
lazy-supplements/src/main.rs
Normal file
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue