mielin_cli/commands/
node.rs

1//! Node command handlers
2
3use crate::config::Config;
4use crate::output::{render_output, OutputFormat};
5use crate::types::{NodeInfo, NodeList, OperationResult};
6use anyhow::Result;
7use clap::Subcommand;
8
9#[derive(Subcommand)]
10pub enum NodeCommands {
11    /// List all nodes in the cluster
12    #[command(alias = "ls")]
13    List,
14    /// Show detailed node information
15    #[command(aliases = ["show", "details"])]
16    Info {
17        /// Node ID to inspect
18        node_id: String,
19    },
20    /// Start the local node
21    Start,
22    /// Stop the local node
23    #[command(aliases = ["kill", "terminate"])]
24    Stop,
25    /// Create a new node
26    #[command(aliases = ["new", "add"])]
27    Create {
28        /// Node role (core, relay, edge)
29        #[arg(short, long, default_value = "edge")]
30        role: String,
31    },
32    /// Join an existing cluster
33    #[command(alias = "connect")]
34    Join {
35        /// Bootstrap node address
36        address: String,
37    },
38    /// Leave the cluster gracefully
39    #[command(aliases = ["disconnect", "depart"])]
40    Leave,
41    /// View or edit node configuration
42    #[command(aliases = ["cfg", "configure"])]
43    Config {
44        /// Configuration key to get/set
45        key: Option<String>,
46        /// Value to set (if not provided, displays current value)
47        value: Option<String>,
48        /// Show all configuration
49        #[arg(short, long)]
50        all: bool,
51    },
52}
53
54pub async fn handle_node_command(action: NodeCommands, format: OutputFormat) -> Result<()> {
55    match action {
56        NodeCommands::List => {
57            let data = mock_node_list();
58            println!("{}", render_output(&data, format)?);
59        }
60        NodeCommands::Info { node_id } => {
61            let result = OperationResult {
62                success: true,
63                message: format!("Node info for {}", node_id),
64                id: Some(node_id),
65            };
66            println!("{}", render_output(&result, format)?);
67        }
68        NodeCommands::Start => {
69            let result = OperationResult {
70                success: true,
71                message: "Node started successfully".to_string(),
72                id: None,
73            };
74            println!("{}", render_output(&result, format)?);
75        }
76        NodeCommands::Stop => {
77            let result = OperationResult {
78                success: true,
79                message: "Node stopped successfully".to_string(),
80                id: None,
81            };
82            println!("{}", render_output(&result, format)?);
83        }
84        NodeCommands::Create { role } => {
85            let result = OperationResult {
86                success: true,
87                message: format!("Created {} node", role),
88                id: Some("new-node-uuid".to_string()),
89            };
90            println!("{}", render_output(&result, format)?);
91        }
92        NodeCommands::Join { address } => {
93            let result = OperationResult {
94                success: true,
95                message: format!("Joined cluster at {}", address),
96                id: None,
97            };
98            println!("{}", render_output(&result, format)?);
99        }
100        NodeCommands::Leave => {
101            let result = OperationResult {
102                success: true,
103                message: "Left cluster gracefully".to_string(),
104                id: None,
105            };
106            println!("{}", render_output(&result, format)?);
107        }
108        NodeCommands::Config { key, value, all } => {
109            let mut config = Config::load()?;
110
111            if all {
112                let config_str = toml::to_string_pretty(&config)?;
113                println!("{}", config_str);
114            } else if let Some(k) = key {
115                if let Some(v) = value {
116                    config.set(&k, &v)?;
117                    config.save()?;
118                    let result = OperationResult {
119                        success: true,
120                        message: format!("Set {} = {}", k, v),
121                        id: None,
122                    };
123                    println!("{}", render_output(&result, format)?);
124                } else if let Some(current_value) = config.get(&k) {
125                    println!("{} = {}", k, current_value);
126                } else {
127                    let result = OperationResult {
128                        success: false,
129                        message: format!("Unknown configuration key: {}", k),
130                        id: None,
131                    };
132                    println!("{}", render_output(&result, format)?);
133                }
134            } else {
135                let result = OperationResult {
136                    success: false,
137                    message: "Please specify a configuration key or use --all".to_string(),
138                    id: None,
139                };
140                println!("{}", render_output(&result, format)?);
141            }
142        }
143    }
144    Ok(())
145}
146
147fn mock_node_list() -> NodeList {
148    NodeList {
149        nodes: vec![
150            NodeInfo {
151                id: "a1b2c3d4-e5f6-7890-abcd-ef1234567890".to_string(),
152                role: "Core".to_string(),
153                state: "Running".to_string(),
154                address: "192.168.1.100:9000".to_string(),
155                agents: 5,
156                uptime: "3d 2h".to_string(),
157                version: "0.0.1".to_string(),
158            },
159            NodeInfo {
160                id: "b2c3d4e5-f6a7-8901-bcde-f12345678901".to_string(),
161                role: "Edge".to_string(),
162                state: "Running".to_string(),
163                address: "192.168.1.101:9000".to_string(),
164                agents: 2,
165                uptime: "1d 5h".to_string(),
166                version: "0.0.1".to_string(),
167            },
168        ],
169        total: 2,
170    }
171}