mirror of https://github.com/buster-so/buster.git
init added in the postgres onboarding
This commit is contained in:
parent
5ac7fc2dad
commit
efca65932e
|
@ -117,12 +117,15 @@ pub async fn init(destination_path: Option<&str>) -> Result<()> {
|
||||||
DatabaseType::Redshift => {
|
DatabaseType::Redshift => {
|
||||||
setup_redshift(buster_creds.url, buster_creds.api_key, &config_path).await
|
setup_redshift(buster_creds.url, buster_creds.api_key, &config_path).await
|
||||||
}
|
}
|
||||||
|
DatabaseType::Postgres => {
|
||||||
|
setup_postgres(buster_creds.url, buster_creds.api_key, &config_path).await
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}",
|
||||||
format!("{} support is coming soon!", db_type).yellow()
|
format!("{} support is coming soon!", db_type).yellow()
|
||||||
);
|
);
|
||||||
println!("Currently, only Redshift is supported.");
|
println!("Currently, only Redshift and Postgres are supported.");
|
||||||
Err(anyhow::anyhow!("Database type not yet implemented"))
|
Err(anyhow::anyhow!("Database type not yet implemented"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,6 +335,195 @@ async fn setup_redshift(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn setup_postgres(
|
||||||
|
buster_url: String,
|
||||||
|
buster_api_key: String,
|
||||||
|
config_path: &Path,
|
||||||
|
) -> Result<()> {
|
||||||
|
println!("{}", "Setting up PostgreSQL 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 {
|
||||||
|
Ok(Validation::Invalid(
|
||||||
|
"Name must contain only alphanumeric characters, dash (-) or underscore (_)"
|
||||||
|
.into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.prompt()?;
|
||||||
|
|
||||||
|
// Collect host
|
||||||
|
let host = Text::new("Enter the PostgreSQL host:")
|
||||||
|
.with_help_message("Example: localhost or db.example.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)
|
||||||
|
let port_str = Text::new("Enter the PostgreSQL port:")
|
||||||
|
.with_default("5432") // Default Postgres port is 5432
|
||||||
|
.with_help_message("Default PostgreSQL port is 5432")
|
||||||
|
.with_validator(|input: &str| match input.parse::<u16>() {
|
||||||
|
Ok(_) => Ok(Validation::Valid),
|
||||||
|
Err(_) => Ok(Validation::Invalid(
|
||||||
|
"Port must be a valid number between 1 and 65535".into(),
|
||||||
|
)),
|
||||||
|
})
|
||||||
|
.prompt()?;
|
||||||
|
let port = port_str.parse::<u16>()?;
|
||||||
|
|
||||||
|
// Collect username
|
||||||
|
let username = Text::new("Enter the PostgreSQL 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 PostgreSQL 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()?;
|
||||||
|
|
||||||
|
// Collect database (optional)
|
||||||
|
let database = Text::new("Enter the PostgreSQL database name (optional):")
|
||||||
|
.with_help_message("Leave blank to access all available databases")
|
||||||
|
.prompt()?;
|
||||||
|
let database = if database.trim().is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(database)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Collect schema (optional)
|
||||||
|
let schema = Text::new("Enter the PostgreSQL schema (optional):")
|
||||||
|
.with_help_message("Leave blank to access all available schemas")
|
||||||
|
.with_default("public") // Default Postgres schema is usually 'public'
|
||||||
|
.prompt()?;
|
||||||
|
let schema = if schema.trim().is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
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());
|
||||||
|
|
||||||
|
// Display database and schema with clear indication if they're empty
|
||||||
|
if let Some(db) = &database {
|
||||||
|
println!("Database: {}", db.cyan());
|
||||||
|
} else {
|
||||||
|
println!("Database: {}", "All databases (null)".cyan());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sch) = &schema {
|
||||||
|
println!("Schema: {}", sch.cyan());
|
||||||
|
} else {
|
||||||
|
println!("Schema: {}", "All schemas (null)".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 API request
|
||||||
|
let request = PostDataSourcesRequest {
|
||||||
|
name: name.clone(),
|
||||||
|
env: "dev".to_string(), // Default to dev environment
|
||||||
|
credential: Credential::Postgres(PostgresCredentials {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
database: database.clone().unwrap_or_default(),
|
||||||
|
schema: schema.clone().unwrap_or_default(),
|
||||||
|
jump_host: None,
|
||||||
|
ssh_username: None,
|
||||||
|
ssh_private_key: None,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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(_) => {
|
||||||
|
spinner.finish_with_message(
|
||||||
|
"✓ Data source created successfully!"
|
||||||
|
.green()
|
||||||
|
.bold()
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
"\nData source '{}' is now available for use with Buster.",
|
||||||
|
name.cyan()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create a copy of the values we need for the config file
|
||||||
|
let db_copy = database.clone();
|
||||||
|
let schema_copy = schema.clone();
|
||||||
|
|
||||||
|
// Create buster.yml file
|
||||||
|
create_buster_config_file(
|
||||||
|
config_path,
|
||||||
|
&name,
|
||||||
|
db_copy.as_deref(),
|
||||||
|
schema_copy.as_deref(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
println!("You can now use this data source with other Buster commands.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Helper function to create buster.yml file
|
// Helper function to create buster.yml file
|
||||||
fn create_buster_config_file(
|
fn create_buster_config_file(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
|
Loading…
Reference in New Issue