commit - 6cf07ef229efdfd94c71c1db45528f686606bd7d
commit + 8f21cf58d999cc6348fbb851e505192645b9e4e6
blob - ce03734d18a04a393b07ddb9f8f2fa8f46efcdff
blob + 87a323f0cd68a2a423e03faa90aa1f49c2644dfc
--- Cargo.lock
+++ Cargo.lock
"aws-config",
"aws-sdk-cognitoidentityprovider",
"clap",
+ "indicatif",
"tokio",
"tracing",
"tracing-subscriber",
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
+name = "console"
+version = "0.16.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b430743a6eb14e9764d4260d4c0d8123087d504eeb9c48f2b2a5e810dd369df4"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "unicode-width",
+ "windows-sys 0.61.2",
+]
+
+[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
name = "equivalent"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
]
[[package]]
+name = "indicatif"
+version = "0.18.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88"
+dependencies = [
+ "console",
+ "portable-atomic",
+ "unicode-width",
+ "unit-prefix",
+ "web-time",
+]
+
+[[package]]
name = "ipnet"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+name = "portable-atomic"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
+
+[[package]]
name = "potential_utf"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
+name = "unicode-width"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+
+[[package]]
+name = "unit-prefix"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3"
+
+[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
]
[[package]]
+name = "web-time"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
blob - 2221b8157522e67a09fad9f0c67101f15f5aff01
blob + 97e6bd47333745582dc8018d107abbc60d57c543
--- Cargo.toml
+++ Cargo.toml
aws-config = { version = "1.8.10", features = ["behavior-version-latest"] }
aws-sdk-cognitoidentityprovider = "1.103.0"
clap = { version = "4.5.52", features = ["derive", "env"] }
+indicatif = "0.18.3"
tokio = { version = "1.48.0", features = ["full"] }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
blob - 5b1b9cc0bfb2cbcaa80fd6bb4625d74cbc26e6f1
blob + 86f1b35adb43ad500a4e6feb0f5530f53cd3bd85
--- src/main.rs
+++ src/main.rs
use aws_sdk_cognitoidentityprovider::Client as CognitoClient;
use aws_sdk_cognitoidentityprovider::types::UserType;
use clap::{ArgAction, Parser, Subcommand};
+use indicatif::{ProgressBar, ProgressStyle};
use tokio::fs::File;
use tokio::io::{self, AsyncBufReadExt, AsyncWrite, AsyncWriteExt, BufReader};
use tokio::sync::Semaphore;
#[tokio::main]
async fn main() -> Result<()> {
- // let users = read_sync_file_to_map(".mail_sync").await?;
-
- // for (email, username) in &users {
- // println!("{email} => {username}");
- // }
let cli = Cli::parse();
init_tracing(cli.verbose);
// 2. Load target e-mails
let emails = load_email_list(emails_list_path).await?;
- info!(total_emails = emails.len(), "loaded target e-mail list");
+ let total_emails = emails.len();
+ info!(total_emails, "loaded target e-mail list");
+ let pb = Arc::new({
+ let bar = ProgressBar::new(total_emails as u64);
+ bar.set_style(
+ ProgressStyle::with_template(
+ "[{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}",
+ )
+ .unwrap_or_else(|_| ProgressStyle::default_bar()),
+ );
+ bar.set_message("processing users");
+ bar
+ });
+
let semaphore = Arc::new(Semaphore::new(concurrency));
let mut handles: Vec<JoinHandle<()>> = Vec::with_capacity(emails.len());
let client_clone = client.clone();
let pool_id = pool_id.to_string();
let groups = groups.to_vec();
+ let email_clone = email.clone();
+ let pb_clone = pb.clone();
let handle = tokio::spawn(async move {
let _permit = permit; // keep permit alive for the duration of this task
.await
{
error!(
- %email,
+ email = %email_clone,
%username,
error = ?err,
"failed to add user to one or more groups"
);
} else {
info!(
- %email,
+ email = %email_clone,
%username,
groups = ?groups,
"user successfully processed for all groups"
);
}
+
+ pb_clone.inc(1);
});
handles.push(handle);
}
}
+ pb.finish_with_message("done");
info!("finished processing all users for add-groups operation");
Ok(())
}