Skip to content

Commit fa8b527

Browse files
[PR #106 ] : Added CLI Version Auto-Fetch & Implement New Subcommands (status, service describe)
Add CLI Version Auto-Fetch & Implement New Subcommands (status, service describe)
2 parents d8345bb + dcac5a5 commit fa8b527

5 files changed

Lines changed: 387 additions & 3 deletions

File tree

cli/src/general.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub struct GeneralData {
77
}
88

99
impl GeneralData {
10-
pub const VERSION: &str = "0.1";
10+
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
1111
pub const AUTHOR: &str = "CortexFlow";
1212
pub const DESCRIPTION: &str = "";
1313

cli/src/main.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod install;
33
mod general;
44
mod uninstall;
55
mod service;
6+
mod status;
67

78
use clap::{ Error, Parser, Subcommand, Args };
89
use clap::command;
@@ -11,7 +12,8 @@ use tracing::debug;
1112
use crate::essential::{ info, update_cli };
1213
use crate::install::install_cortexflow;
1314
use crate::uninstall::uninstall;
14-
use crate::service::list_services;
15+
use crate::service::{list_services, describe_service};
16+
use crate::status::status_command;
1517

1618
use crate::general::GeneralData;
1719

@@ -46,6 +48,8 @@ enum Commands {
4648
Info,
4749
#[command(name="service")]
4850
Service(ServiceArgs),
51+
#[command(name="status")]
52+
Status(StatusArgs),
4953
}
5054
#[derive(Args, Debug, Clone)]
5155
struct SetArgs {
@@ -65,6 +69,20 @@ enum ServiceCommands {
6569
#[arg(long)]
6670
namespace: Option<String>,
6771
},
72+
#[command(name="describe")]
73+
Describe {
74+
service_name: String,
75+
#[arg(long)]
76+
namespace: Option<String>,
77+
},
78+
}
79+
80+
#[derive(Args, Debug, Clone)]
81+
struct StatusArgs {
82+
#[arg(long)]
83+
output: Option<String>,
84+
#[arg(long)]
85+
namespace: Option<String>,
6886
}
6987

7088
fn args_parser() -> Result<(), Error> {
@@ -103,8 +121,16 @@ fn args_parser() -> Result<(), Error> {
103121
list_services(namespace);
104122
Ok(())
105123
}
124+
ServiceCommands::Describe { service_name, namespace } => {
125+
describe_service(service_name, namespace);
126+
Ok(())
127+
}
106128
}
107129
}
130+
Some(Commands::Status(status_args)) => {
131+
status_command(status_args.output, status_args.namespace);
132+
Ok(())
133+
}
108134
None => {
109135
eprintln!("CLI unknown argument. Cli arguments passed: {:?}", args.cmd);
110136
Ok(())

cli/src/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ pub mod essential;
22
pub mod install;
33
pub mod general;
44
pub mod uninstall;
5-
pub mod service;
5+
pub mod service;
6+
pub mod status;

cli/src/service.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,58 @@
11
use std::process::Command;
22
use std::str;
33

4+
fn check_namespace_exists(namespace: &str) -> bool {
5+
let output = Command::new("kubectl")
6+
.args(["get", "namespace", namespace])
7+
.output();
8+
9+
match output {
10+
Ok(output) => output.status.success(),
11+
Err(_) => false,
12+
}
13+
}
14+
15+
fn get_available_namespaces() -> Vec<String> {
16+
let output = Command::new("kubectl")
17+
.args(["get", "namespaces", "--no-headers", "-o", "custom-columns=NAME:.metadata.name"])
18+
.output();
19+
20+
match output {
21+
Ok(output) if output.status.success() => {
22+
let stdout = str::from_utf8(&output.stdout).unwrap_or("");
23+
stdout.lines()
24+
.map(|line| line.trim().to_string())
25+
.filter(|line| !line.is_empty())
26+
.collect()
27+
}
28+
_ => Vec::new(),
29+
}
30+
}
31+
432
pub fn list_services(namespace: Option<String>) {
533
let ns = namespace.unwrap_or_else(|| "cortexflow".to_string());
634

735
println!("Listing services in namespace: {}", ns);
836

37+
// Check if namespace exists first
38+
if !check_namespace_exists(&ns) {
39+
let available_namespaces = get_available_namespaces();
40+
41+
println!("\n❌ Namespace '{}' not found", ns);
42+
println!("{}", "=".repeat(50));
43+
44+
if !available_namespaces.is_empty() {
45+
println!("\n📋 Available namespaces:");
46+
for available_ns in &available_namespaces {
47+
println!(" • {}", available_ns);
48+
}
49+
} else {
50+
println!("No namespaces found in the cluster.");
51+
}
52+
53+
std::process::exit(1);
54+
}
55+
956
// kubectl command to get services
1057
let output = Command::new("kubectl")
1158
.args(["get", "pods", "-n", &ns, "--no-headers"])
@@ -56,4 +103,62 @@ pub fn list_services(namespace: Option<String>) {
56103
std::process::exit(1);
57104
}
58105
}
106+
}
107+
108+
pub fn describe_service(service_name: String, namespace: Option<String>) {
109+
let ns = namespace.unwrap_or_else(|| "cortexflow".to_string());
110+
111+
println!("Describing service '{}' in namespace: {}", service_name, ns);
112+
println!("{}", "=".repeat(60));
113+
114+
// Check if namespace exists first
115+
if !check_namespace_exists(&ns) {
116+
let available_namespaces = get_available_namespaces();
117+
118+
println!("\n❌ Namespace '{}' not found", ns);
119+
println!("{}", "=".repeat(50));
120+
121+
if !available_namespaces.is_empty() {
122+
println!("\n📋 Available namespaces:");
123+
for available_ns in &available_namespaces {
124+
println!(" • {}", available_ns);
125+
}
126+
println!("\nTry: cortex service describe {} --namespace <namespace-name>", service_name);
127+
} else {
128+
println!("No namespaces found in the cluster.");
129+
}
130+
131+
std::process::exit(1);
132+
}
133+
134+
// Execute kubectl describe pod command
135+
let output = Command::new("kubectl")
136+
.args(["describe", "pod", &service_name, "-n", &ns])
137+
.output();
138+
139+
match output {
140+
Ok(output) => {
141+
if !output.status.success() {
142+
let error = str::from_utf8(&output.stderr).unwrap_or("Unknown error");
143+
eprintln!("Error executing kubectl describe: {}", error);
144+
eprintln!("Make sure the pod '{}' exists in namespace '{}'", service_name, ns);
145+
std::process::exit(1);
146+
}
147+
148+
let stdout = str::from_utf8(&output.stdout).unwrap_or("");
149+
150+
if stdout.trim().is_empty() {
151+
println!("No description found for pod '{}'", service_name);
152+
return;
153+
}
154+
155+
// Print the full kubectl describe output
156+
println!("{}", stdout);
157+
}
158+
Err(err) => {
159+
eprintln!("Failed to execute kubectl describe command: {}", err);
160+
eprintln!("Make sure kubectl is installed and configured properly");
161+
std::process::exit(1);
162+
}
163+
}
59164
}

0 commit comments

Comments
 (0)