Skip to content

Commit 6f03ed3

Browse files
author
Chris
committed
added better account selection
1 parent 6747c71 commit 6f03ed3

3 files changed

Lines changed: 74 additions & 21 deletions

File tree

src/cli.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ pub enum AccountAction {
9898

9999
#[derive(Args, Debug)]
100100
pub struct AccountId {
101-
/// Account slug to switch to
102-
pub account: String,
101+
/// Account slug to switch to (interactive selection if omitted)
102+
pub account: Option<String>,
103103
}
104104

105105
#[derive(Args, Debug)]
@@ -217,9 +217,9 @@ pub enum AddOnAction {
217217

218218
#[derive(Args, Debug)]
219219
pub struct ClusterId {
220-
/// Cluster name
220+
/// Cluster name (interactive selection if omitted)
221221
#[arg(long)]
222-
pub cluster: String,
222+
pub cluster: Option<String>,
223223
}
224224

225225
#[derive(Args, Debug)]

src/commands/account.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,51 @@
1+
use std::io::{self, BufRead, Write};
2+
13
use colored::Colorize;
24

35
use crate::cli::AccountId;
4-
use crate::client::{CanineClient, CanineError};
6+
use crate::client::{Account, CanineClient, CanineError};
57
use crate::config::CanineConfig;
68

9+
fn select_account(accounts: &[Account]) -> Result<String, Box<dyn std::error::Error>> {
10+
if accounts.is_empty() {
11+
return Err("No accounts found".into());
12+
}
13+
println!("\nSelect an account:");
14+
for (i, a) in accounts.iter().enumerate() {
15+
println!(" [{}] {}", (i + 1).to_string().cyan(), a.slug);
16+
}
17+
print!("\n{} ", "Enter number:".bold());
18+
io::stdout().flush().unwrap();
19+
let mut input = String::new();
20+
io::stdin().lock().read_line(&mut input)?;
21+
let choice: usize = input.trim().parse().map_err(|_| "Invalid selection")?;
22+
if choice < 1 || choice > accounts.len() {
23+
return Err(format!("Selection out of range (1-{})", accounts.len()).into());
24+
}
25+
Ok(accounts[choice - 1].slug.clone())
26+
}
27+
728
pub async fn handle_change_account(
829
config: &CanineConfig,
930
client: &CanineClient,
1031
account_id: &AccountId,
1132
) -> Result<(), Box<dyn std::error::Error>> {
1233
let response = client.me().await?;
1334

14-
if response
15-
.accounts
16-
.iter()
17-
.any(|item| item.slug.contains(&account_id.account))
18-
{
19-
config.change_account(&account_id.account)?;
20-
println!("{} Switched to account {}", "✓".green(), account_id.account.cyan());
21-
Ok(())
35+
let slug = if let Some(ref account) = account_id.account {
36+
if response.accounts.iter().any(|item| item.slug.contains(account)) {
37+
account.clone()
38+
} else {
39+
return Err(Box::new(CanineError::NoAccount(format!(
40+
"Account {} not found",
41+
account
42+
))));
43+
}
2244
} else {
23-
Err(Box::new(CanineError::NoAccount(format!(
24-
"Account {} not found",
25-
account_id.account
26-
))))
27-
}
45+
select_account(&response.accounts)?
46+
};
47+
48+
config.change_account(&slug)?;
49+
println!("{} Switched to account {}", "✓".green(), slug.cyan());
50+
Ok(())
2851
}

src/commands/cluster.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use tabled::Table;
22
use colored::Colorize;
3-
use std::io;
3+
use std::io::{self, BufRead, Write};
44
use std::process::Command;
55
use crate::cli::ClusterId;
66
use crate::client::CanineClient;
@@ -41,12 +41,41 @@ pub async fn handle_list(client: &CanineClient) -> Result<(), Box<dyn std::error
4141
Ok(())
4242
}
4343

44+
fn select_cluster_name(clusters: &[crate::client::Cluster]) -> Result<String, Box<dyn std::error::Error>> {
45+
if clusters.is_empty() {
46+
return Err("No clusters found".into());
47+
}
48+
println!("\nSelect a cluster:");
49+
for (i, c) in clusters.iter().enumerate() {
50+
println!(" [{}] {} ({})", (i + 1).to_string().cyan(), c.name, format!("{}", c.status).dimmed());
51+
}
52+
print!("\n{} ", "Enter number:".bold());
53+
io::stdout().flush().unwrap();
54+
let mut input = String::new();
55+
io::stdin().lock().read_line(&mut input)?;
56+
let choice: usize = input.trim().parse().map_err(|_| "Invalid selection")?;
57+
if choice < 1 || choice > clusters.len() {
58+
return Err(format!("Selection out of range (1-{})", clusters.len()).into());
59+
}
60+
Ok(clusters[choice - 1].name.clone())
61+
}
62+
63+
async fn resolve_cluster_name(client: &CanineClient, id: &ClusterId) -> Result<String, Box<dyn std::error::Error>> {
64+
if let Some(ref name) = id.cluster {
65+
Ok(name.clone())
66+
} else {
67+
let clusters = client.get_clusters().await?.clusters;
68+
select_cluster_name(&clusters)
69+
}
70+
}
71+
4472
pub async fn handle_download_kubeconfig(
4573
config: &CanineConfig,
4674
client: &CanineClient,
4775
id: &ClusterId,
4876
) -> Result<(), Box<dyn std::error::Error>> {
49-
let kubeconfig = client.download_kubeconfig_file(&id.cluster).await?;
77+
let cluster_name = resolve_cluster_name(client, id).await?;
78+
let kubeconfig = client.download_kubeconfig_file(&cluster_name).await?;
5079
let yaml = kubeconfig_to_yaml(&kubeconfig.kubeconfig)?;
5180
config.save_kubeconfig(yaml)?;
5281
Ok(())
@@ -66,7 +95,8 @@ pub async fn handle_connect(
6695
std::process::exit(1);
6796
}
6897
println!("{} telepresence found", "✓".green());
69-
let kubeconfig = client.download_kubeconfig_file(&id.cluster).await?;
98+
let cluster_name = resolve_cluster_name(client, id).await?;
99+
let kubeconfig = client.download_kubeconfig_file(&cluster_name).await?;
70100
let yaml = kubeconfig_to_yaml(&kubeconfig.kubeconfig)?;
71101
config.save_kubeconfig(yaml)?;
72102

0 commit comments

Comments
 (0)