feat(ui): add colored output and tables for project info
This commit is contained in:
151
Cargo.lock
generated
151
Cargo.lock
generated
@@ -255,6 +255,26 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "3.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "comfy-table"
|
||||
version = "7.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b03b7db8e0b4b2fdad6c551e634134e99ec000e5c8c3b6856c65e8bbaded7a3b"
|
||||
dependencies = [
|
||||
"crossterm",
|
||||
"unicode-segmentation",
|
||||
"unicode-width 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.16.1"
|
||||
@@ -274,6 +294,29 @@ version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"document-features",
|
||||
"parking_lot",
|
||||
"rustix",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.21.3"
|
||||
@@ -330,6 +373,15 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "document-features"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
|
||||
dependencies = [
|
||||
"litrs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.20"
|
||||
@@ -849,6 +901,12 @@ version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.14"
|
||||
@@ -1006,6 +1064,8 @@ version = "0.0.1"
|
||||
dependencies = [
|
||||
"bollard",
|
||||
"clap",
|
||||
"colored",
|
||||
"comfy-table",
|
||||
"futures",
|
||||
"indicatif",
|
||||
"miette",
|
||||
@@ -1876,13 +1936,22 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.53.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1894,6 +1963,22 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm 0.52.6",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.5"
|
||||
@@ -1901,58 +1986,106 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.53.1",
|
||||
"windows_aarch64_msvc 0.53.1",
|
||||
"windows_i686_gnu 0.53.1",
|
||||
"windows_i686_gnullvm 0.53.1",
|
||||
"windows_i686_msvc 0.53.1",
|
||||
"windows_x86_64_gnu 0.53.1",
|
||||
"windows_x86_64_gnullvm 0.53.1",
|
||||
"windows_x86_64_msvc 0.53.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.53.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.53.1"
|
||||
|
||||
@@ -9,6 +9,8 @@ license = "MIT"
|
||||
[dependencies]
|
||||
bollard = "0.19.4"
|
||||
clap = { version = "4.5.53", features = ["derive"] }
|
||||
colored = "3.0.0"
|
||||
comfy-table = "7.2.1"
|
||||
futures = "0.3.31"
|
||||
indicatif = { version = "0.18.3", features = ["improved_unicode"] }
|
||||
miette = { version = "7.6.0", features = ["fancy"] }
|
||||
|
||||
2
pgd.toml
2
pgd.toml
@@ -1,3 +1,3 @@
|
||||
version = "18.1"
|
||||
password = "GypnQVF1uV23DWvp"
|
||||
password = "a7BASi7P3gCgc0Xx"
|
||||
port = 5433
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use miette::{bail, miette};
|
||||
|
||||
use colored::Colorize;
|
||||
use comfy_table::{Attribute, Cell, Color, ContentArrangement, Table, presets::UTF8_FULL};
|
||||
use miette::Result;
|
||||
|
||||
use crate::{
|
||||
@@ -12,7 +16,7 @@ mod docker;
|
||||
mod utils;
|
||||
|
||||
const MAX_RETRIES: u32 = 10;
|
||||
const VERIFY_DURATION_SECS: u64 = 10;
|
||||
const VERIFY_DURATION_SECS: u64 = 5;
|
||||
|
||||
pub struct Controller {
|
||||
docker: DockerController,
|
||||
@@ -35,7 +39,7 @@ impl Controller {
|
||||
return self.reconcile(project).await;
|
||||
}
|
||||
|
||||
println!("Initializing new pgd project...");
|
||||
println!("{}", "Initializing new pgd project...".cyan());
|
||||
|
||||
let mut versions = self.docker.available_versions().await?;
|
||||
versions.sort();
|
||||
@@ -50,15 +54,48 @@ impl Controller {
|
||||
};
|
||||
let project = Project::new(config)?;
|
||||
|
||||
println!("Created pgd.toml in {}", project.path.display());
|
||||
println!(" Project: {}", project.name);
|
||||
println!(" PostgreSQL version: {}", project.config.version);
|
||||
println!(" Port: {}", project.config.port);
|
||||
println!(" Password: {}", "*".repeat(project.config.password.len()));
|
||||
println!(
|
||||
"\n{} {}\n",
|
||||
"Created pgd.toml in",
|
||||
project.path.display().to_string().bright_white().bold()
|
||||
);
|
||||
|
||||
let mut table = Table::new();
|
||||
table
|
||||
.load_preset(UTF8_FULL)
|
||||
.set_content_arrangement(ContentArrangement::Dynamic)
|
||||
.set_style(comfy_table::TableComponent::MiddleIntersections, ' ')
|
||||
.set_header(vec![
|
||||
Cell::new("Instance Configuration").add_attribute(Attribute::Bold),
|
||||
]);
|
||||
|
||||
use comfy_table::TableComponent::*;
|
||||
table.set_style(TopLeftCorner, '╭');
|
||||
table.set_style(TopRightCorner, '╮');
|
||||
table.set_style(BottomLeftCorner, '╰');
|
||||
table.set_style(BottomRightCorner, '╯');
|
||||
table.add_row(vec![
|
||||
Cell::new("Project").fg(Color::White),
|
||||
Cell::new(&project.name).add_attribute(Attribute::Bold),
|
||||
]);
|
||||
table.add_row(vec![
|
||||
Cell::new("PostgreSQL Version").fg(Color::White),
|
||||
Cell::new(project.config.version.to_string()).add_attribute(Attribute::Bold),
|
||||
]);
|
||||
table.add_row(vec![
|
||||
Cell::new("Port").fg(Color::White),
|
||||
Cell::new(project.config.port.to_string()).add_attribute(Attribute::Bold),
|
||||
]);
|
||||
table.add_row(vec![
|
||||
Cell::new("Password").fg(Color::White),
|
||||
Cell::new("*".repeat(project.config.password.len())).fg(Color::DarkGrey),
|
||||
]);
|
||||
|
||||
println!("{table}");
|
||||
|
||||
self.reconcile(&project).await?;
|
||||
|
||||
println!("\nProject initialized successfully!");
|
||||
println!("\n{}", "✓ Project initialized successfully!".green().bold());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -98,32 +135,45 @@ impl Controller {
|
||||
.is_container_running_by_id(&container_id)
|
||||
.await?
|
||||
{
|
||||
println!("Container is already running");
|
||||
println!("{}", "Container is already running".white());
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
|
||||
let spinner = ProgressBar::new_spinner();
|
||||
spinner.enable_steady_tick(Duration::from_millis(100));
|
||||
spinner.set_style(
|
||||
ProgressStyle::default_spinner()
|
||||
.template("{spinner:.green} {msg}")
|
||||
.template("{spinner:.cyan} {msg}")
|
||||
.unwrap(),
|
||||
);
|
||||
spinner.set_message("Starting container...");
|
||||
|
||||
for attempt in 1..=MAX_RETRIES {
|
||||
spinner.set_message(format!("Starting container (attempt {}/{})", attempt, MAX_RETRIES));
|
||||
spinner.set_message(format!(
|
||||
"Starting container (attempt {}/{})",
|
||||
attempt, MAX_RETRIES
|
||||
));
|
||||
|
||||
let result = self.try_starting_container(&container_id, &spinner).await;
|
||||
|
||||
match result {
|
||||
Ok(_) => {
|
||||
spinner.finish_with_message("Container started successfully");
|
||||
spinner.finish_with_message(format!(
|
||||
"{}",
|
||||
"Container started successfully".green().bold()
|
||||
));
|
||||
return Ok(());
|
||||
}
|
||||
Err(err) => {
|
||||
spinner.set_message(format!("Attempt {}/{} failed: {}", attempt, MAX_RETRIES, err));
|
||||
spinner.set_message(format!(
|
||||
"{} {}/{} failed: {}",
|
||||
"Attempt".yellow(),
|
||||
attempt,
|
||||
MAX_RETRIES,
|
||||
err
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +182,7 @@ impl Controller {
|
||||
}
|
||||
}
|
||||
|
||||
spinner.finish_with_message("Failed to start container");
|
||||
spinner.finish_with_message(format!("{}", "Failed to start container".red()));
|
||||
miette::bail!("Failed to start container after {} attempts", MAX_RETRIES)
|
||||
}
|
||||
|
||||
@@ -144,18 +194,19 @@ impl Controller {
|
||||
match self.docker.start_container_by_id(container_id).await {
|
||||
Ok(_) => {
|
||||
spinner.set_message(format!(
|
||||
"Verifying container is running ({}s)...",
|
||||
"{} ({}s)...",
|
||||
"Verifying container is running".cyan(),
|
||||
VERIFY_DURATION_SECS
|
||||
));
|
||||
|
||||
for i in 0..VERIFY_DURATION_SECS {
|
||||
spinner.set_message(format!(
|
||||
"Verifying container stability ({}/{}s)",
|
||||
"{} ({}/{}s)",
|
||||
"Verifying container stability".cyan(),
|
||||
i + 1,
|
||||
VERIFY_DURATION_SECS
|
||||
));
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||
spinner.tick();
|
||||
}
|
||||
|
||||
if self.docker.is_container_running_by_id(container_id).await? {
|
||||
@@ -175,7 +226,11 @@ impl Controller {
|
||||
project: &Project,
|
||||
state: &mut StateManager,
|
||||
) -> Result<String, miette::Error> {
|
||||
println!("Creating container {}...", project.container_name());
|
||||
println!(
|
||||
"{} {}",
|
||||
"Creating container".cyan(),
|
||||
project.container_name().yellow()
|
||||
);
|
||||
let id = self
|
||||
.docker
|
||||
.create_postgres_container(
|
||||
@@ -185,7 +240,7 @@ impl Controller {
|
||||
project.config.port,
|
||||
)
|
||||
.await?;
|
||||
println!("Container created successfully");
|
||||
println!("{}", "Container created successfully".green());
|
||||
state.set(
|
||||
project.name.clone(),
|
||||
crate::state::InstanceState::new(
|
||||
|
||||
@@ -9,6 +9,7 @@ use bollard::{
|
||||
},
|
||||
secret::ContainerCreateBody,
|
||||
};
|
||||
use colored::Colorize;
|
||||
use indicatif::MultiProgress;
|
||||
use miette::{Context, IntoDiagnostic, Result};
|
||||
use tracing::info;
|
||||
@@ -58,11 +59,11 @@ impl DockerController {
|
||||
|
||||
let multi = MultiProgress::new();
|
||||
|
||||
println!("Downloading {image}");
|
||||
println!("{} {}", "Downloading".cyan(), image.yellow());
|
||||
|
||||
download::perform_download(multi, download_progress).await?;
|
||||
|
||||
println!("Download complete!");
|
||||
println!("{}", "Download complete!".green().bold());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user