ok init looking good.

This commit is contained in:
dal 2025-02-25 11:22:53 -07:00
parent 0d45439173
commit 3d77316fe6
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
1 changed files with 79 additions and 14 deletions

View File

@ -1,9 +1,11 @@
use anyhow::Result;
use colored::*;
use inquire::{Select, Text, Password, validator::Validation};
use inquire::{Select, Text, Password, validator::Validation, Confirm};
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::error::Error;
use indicatif::{ProgressBar, ProgressStyle};
use std::time::Duration;
use crate::utils::{
buster_credentials::get_and_validate_buster_credentials,
@ -43,17 +45,28 @@ struct RedshiftCredentials {
pub async fn init() -> Result<()> {
println!("{}", "Initializing Buster...".bold().green());
// Check for Buster credentials
println!("Checking for Buster credentials...");
// Check for Buster credentials with progress indicator
let spinner = ProgressBar::new_spinner();
spinner.set_style(
ProgressStyle::default_spinner()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
.template("{spinner:.green} {msg}")
.unwrap(),
);
spinner.set_message("Checking for Buster credentials...");
spinner.enable_steady_tick(Duration::from_millis(100));
let buster_creds = match get_and_validate_buster_credentials().await {
Ok(creds) => creds,
Ok(creds) => {
spinner.finish_with_message("✓ Buster credentials found".green().to_string());
creds
},
Err(_) => {
println!("{}", "No valid Buster credentials found.".red());
spinner.finish_with_message("✗ No valid Buster credentials found".red().to_string());
println!("Please run {} first.", "buster auth".cyan());
return Err(anyhow::anyhow!("No valid Buster credentials found"));
}
};
println!("{}", "✓ Buster credentials found".green());
// Select database type
let db_types = vec![
@ -75,19 +88,23 @@ pub async fn init() -> Result<()> {
DatabaseType::Redshift => setup_redshift(buster_creds.url, buster_creds.api_key).await,
_ => {
println!("{}", format!("{} support is coming soon!", db_type).yellow());
println!("Currently, only Redshift is supported.");
Err(anyhow::anyhow!("Database type not yet implemented"))
}
}
}
async fn setup_redshift(buster_url: String, buster_api_key: String) -> Result<()> {
println!("{}", "Setting up Redshift connection...".bold());
println!("{}", "Setting up Redshift connection...".bold().green());
// Collect name (with validation)
let name_regex = Regex::new(r"^[a-zA-Z0-9_-]+$")?;
let name = Text::new("Enter a unique name for this data source:")
.with_help_message("Only alphanumeric characters, dash (-) and underscore (_) allowed")
.with_validator(move |input: &str| {
if input.trim().is_empty() {
return Ok(Validation::Invalid("Name cannot be empty".into()));
}
if name_regex.is_match(input) {
Ok(Validation::Valid)
} else {
@ -99,6 +116,12 @@ async fn setup_redshift(buster_url: String, buster_api_key: String) -> Result<()
// Collect host
let host = Text::new("Enter the Redshift host:")
.with_help_message("Example: my-cluster.abc123xyz789.us-west-2.redshift.amazonaws.com")
.with_validator(|input: &str| {
if input.trim().is_empty() {
return Ok(Validation::Invalid("Host cannot be empty".into()));
}
Ok(Validation::Valid)
})
.prompt()?;
// Collect port (with validation)
@ -116,10 +139,22 @@ async fn setup_redshift(buster_url: String, buster_api_key: String) -> Result<()
// Collect username
let username = Text::new("Enter the Redshift username:")
.with_validator(|input: &str| {
if input.trim().is_empty() {
return Ok(Validation::Invalid("Username cannot be empty".into()));
}
Ok(Validation::Valid)
})
.prompt()?;
// Collect password (masked)
let password = Password::new("Enter the Redshift password:")
.with_validator(|input: &str| {
if input.trim().is_empty() {
return Ok(Validation::Invalid("Password cannot be empty".into()));
}
Ok(Validation::Valid)
})
.without_confirmation()
.prompt()?;
@ -143,6 +178,25 @@ async fn setup_redshift(buster_url: String, buster_api_key: String) -> Result<()
Some(schema)
};
// Show summary and confirm
println!("\n{}", "Connection Summary:".bold());
println!("Name: {}", name.cyan());
println!("Host: {}", host.cyan());
println!("Port: {}", port.to_string().cyan());
println!("Username: {}", username.cyan());
println!("Password: {}", "********".cyan());
println!("Database: {}", database.clone().unwrap_or_else(|| "All databases".to_string()).cyan());
println!("Schema: {}", schema.clone().unwrap_or_else(|| "All schemas".to_string()).cyan());
let confirm = Confirm::new("Do you want to create this data source?")
.with_default(true)
.prompt()?;
if !confirm {
println!("{}", "Data source creation cancelled.".yellow());
return Ok(());
}
// Create credentials
let redshift_creds = RedshiftCredentials {
host,
@ -172,19 +226,30 @@ async fn setup_redshift(buster_url: String, buster_api_key: String) -> Result<()
),
};
// Send to API
println!("Sending credentials to Buster API...");
// Send to API with progress indicator
let spinner = ProgressBar::new_spinner();
spinner.set_style(
ProgressStyle::default_spinner()
.tick_chars("⠁⠂⠄⡀⢀⠠⠐⠈ ")
.template("{spinner:.green} {msg}")
.unwrap(),
);
spinner.set_message("Sending credentials to Buster API...");
spinner.enable_steady_tick(Duration::from_millis(100));
let client = BusterClient::new(buster_url, buster_api_key)?;
match client.post_data_sources(vec![request]).await {
Ok(_) => {
println!("{}", "✓ Data source created successfully!".green().bold());
println!("Data source '{}' is now available for use with Buster.", name.cyan());
spinner.finish_with_message("✓ Data source created successfully!".green().bold().to_string());
println!("\nData source '{}' is now available for use with Buster.", name.cyan());
println!("You can now use this data source with other Buster commands.");
Ok(())
},
Err(e) => {
println!("{}", "✗ Failed to create data source".red().bold());
println!("Error: {}", e);
spinner.finish_with_message("✗ Failed to create data source".red().bold().to_string());
println!("\nError: {}", e);
println!("Please check your credentials and try again.");
Err(anyhow::anyhow!("Failed to create data source: {}", e))
}
}