use std::fmt;
use std::sync::Arc;
use std::time::Duration;
use secrecy::SecretString;
use crate::api::auth::AuthMethod;
use crate::circuit_breaker::CircuitBreakerConfig;
use crate::types::error::VaultError;
use crate::types::response::AuthInfo;
pub struct BlockingVaultClient {
pub(crate) inner: super::VaultClient,
pub(crate) rt: Arc<tokio::runtime::Runtime>,
}
impl fmt::Debug for BlockingVaultClient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BlockingVaultClient")
.field("inner", &self.inner)
.finish_non_exhaustive()
}
}
const _: () = {
fn _assert_send_sync<T: Send + Sync>() {}
fn _assert() {
_assert_send_sync::<BlockingVaultClient>();
}
};
impl BlockingVaultClient {
pub fn new(address: &str, token: &str) -> Result<Self, VaultError> {
Self::builder().address(address).token_str(token).build()
}
pub fn from_env() -> Result<Self, VaultError> {
BlockingClientBuilder::from_env().build()
}
pub fn builder() -> BlockingClientBuilder {
BlockingClientBuilder(super::ClientBuilder::default())
}
pub fn set_token(&self, token: SecretString) -> Result<(), VaultError> {
self.inner.set_token(token)
}
#[must_use]
pub fn with_namespace(&self, ns: &str) -> Self {
BlockingVaultClient {
inner: self.inner.with_namespace(ns),
rt: Arc::clone(&self.rt),
}
}
#[must_use]
pub fn with_wrap_ttl(&self, ttl: &str) -> Self {
BlockingVaultClient {
inner: self.inner.with_wrap_ttl(ttl),
rt: Arc::clone(&self.rt),
}
}
}
#[must_use]
pub struct BlockingClientBuilder(super::ClientBuilder);
impl BlockingClientBuilder {
pub fn from_env() -> Self {
BlockingClientBuilder(super::ClientBuilder::from_env())
}
pub fn address(mut self, addr: &str) -> Self {
self.0 = self.0.address(addr);
self
}
pub fn token(mut self, token: SecretString) -> Self {
self.0 = self.0.token(token);
self
}
pub fn token_str(self, token: &str) -> Self {
self.token(SecretString::from(token))
}
pub fn namespace(mut self, ns: &str) -> Self {
self.0 = self.0.namespace(ns);
self
}
pub fn timeout(mut self, timeout: Duration) -> Self {
self.0 = self.0.timeout(timeout);
self
}
pub fn max_retries(mut self, n: u32) -> Self {
self.0 = self.0.max_retries(n);
self
}
pub fn initial_retry_delay(mut self, d: Duration) -> Self {
self.0 = self.0.initial_retry_delay(d);
self
}
pub fn wrap_ttl(mut self, ttl: &str) -> Self {
self.0 = self.0.wrap_ttl(ttl);
self
}
pub fn forward_to_leader(mut self, yes: bool) -> Self {
self.0 = self.0.forward_to_leader(yes);
self
}
pub fn cli_mode(mut self, yes: bool) -> Self {
self.0 = self.0.cli_mode(yes);
self
}
pub fn danger_disable_tls_verify(mut self, yes: bool) -> Self {
self.0 = self.0.danger_disable_tls_verify(yes);
self
}
pub fn ca_cert_pem(mut self, pem: impl Into<Vec<u8>>) -> Self {
self.0 = self.0.ca_cert_pem(pem);
self
}
pub fn client_cert_pem(mut self, cert: impl Into<Vec<u8>>, key: impl Into<Vec<u8>>) -> Self {
self.0 = self.0.client_cert_pem(cert, key);
self
}
pub fn auth_method(mut self, method: impl AuthMethod + 'static) -> Self {
self.0 = self.0.auth_method(method);
self
}
pub fn circuit_breaker(mut self, config: CircuitBreakerConfig) -> Self {
self.0 = self.0.circuit_breaker(config);
self
}
pub fn on_token_changed(mut self, f: impl Fn(&AuthInfo) + Send + Sync + 'static) -> Self {
self.0 = self.0.on_token_changed(f);
self
}
pub fn with_reqwest_client(mut self, client: reqwest::Client) -> Self {
self.0 = self.0.with_reqwest_client(client);
self
}
pub fn build(self) -> Result<BlockingVaultClient, VaultError> {
if tokio::runtime::Handle::try_current().is_ok() {
return Err(VaultError::Config(
"BlockingVaultClient cannot be created inside a Tokio runtime. \
Reason: BlockingVaultClient spawns its own single-threaded Tokio runtime, \
and nested runtimes are not supported. \
Fix: use VaultClient (async) with .await, or call \
BlockingVaultClient::new() from a std::thread outside the existing runtime."
.into(),
));
}
let inner = self.0.build()?;
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| VaultError::Config(format!("tokio runtime: {e}")))?;
Ok(BlockingVaultClient {
inner,
rt: Arc::new(rt),
})
}
}