fix(bootstrap): Skip early SecretsManager init if bootstrap incomplete, add logging

- Only initialize SecretsManager early if .env and init.json exist
- Fix error handling for bootstrap() - no longer silently ignores failures
- Add detailed logging to trace bootstrap flow
- Log component installation decisions (installed, needs_install flags)
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-12-09 08:10:47 -03:00
parent 715a60315e
commit 4ea3b76adc
2 changed files with 42 additions and 11 deletions

View file

@ -512,6 +512,8 @@ impl BootstrapManager {
}
pub async fn bootstrap(&mut self) -> Result<()> {
info!("=== BOOTSTRAP STARTING ===");
// Generate certificates first (including for Vault)
info!("Generating TLS certificates...");
if let Err(e) = self.generate_certificates().await {
@ -552,13 +554,20 @@ impl BootstrapManager {
for component in required_components {
// For vault, also check if it needs initialization
let is_installed = pm.is_installed(component);
let needs_install = if component == "vault" {
!pm.is_installed(component) || vault_needs_setup
!is_installed || vault_needs_setup
} else {
!pm.is_installed(component)
!is_installed
};
info!(
"Component {}: installed={}, needs_install={}, vault_needs_setup={}",
component, is_installed, needs_install, vault_needs_setup
);
if needs_install {
info!("Installing/configuring component: {}", component);
// Quick check if component might be running - don't hang on this
let bin_path = pm.base_path.join("bin").join(component);
let binary_name = pm
@ -630,6 +639,7 @@ impl BootstrapManager {
// After Vault is installed, START the server then initialize it
if component == "vault" {
info!("=== VAULT SETUP BLOCK ENTERED ===");
info!("Starting Vault server...");
match pm.start("vault") {
Ok(_) => {
@ -697,6 +707,7 @@ impl BootstrapManager {
}
}
}
info!("=== BOOTSTRAP COMPLETED SUCCESSFULLY ===");
Ok(())
}

View file

@ -303,15 +303,28 @@ async fn main() -> std::io::Result<()> {
// Load .env for VAULT_* variables only (all other secrets come from Vault)
dotenvy::dotenv().ok();
// Initialize SecretsManager early - this connects to Vault if configured
// Only VAULT_ADDR, VAULT_TOKEN, and VAULT_SKIP_VERIFY should be in .env
if let Err(e) = crate::shared::utils::init_secrets_manager().await {
warn!(
"Failed to initialize SecretsManager: {}. Falling back to env vars.",
e
);
// Check if bootstrap is complete BEFORE trying to init SecretsManager
let env_path_early = std::path::Path::new("./.env");
let vault_init_path_early = std::path::Path::new("./botserver-stack/conf/vault/init.json");
let bootstrap_ready = env_path_early.exists() && vault_init_path_early.exists() && {
std::fs::read_to_string(env_path_early)
.map(|content| content.contains("VAULT_TOKEN="))
.unwrap_or(false)
};
// Only initialize SecretsManager early if bootstrap is complete
// Otherwise, bootstrap will handle it
if bootstrap_ready {
if let Err(e) = crate::shared::utils::init_secrets_manager().await {
warn!(
"Failed to initialize SecretsManager: {}. Falling back to env vars.",
e
);
} else {
info!("SecretsManager initialized - fetching secrets from Vault");
}
} else {
info!("SecretsManager initialized - fetching secrets from Vault");
trace!("Bootstrap not complete - skipping early SecretsManager init");
}
// Initialize logger early to capture all logs with filters for noisy libraries
@ -508,8 +521,15 @@ async fn main() -> std::io::Result<()> {
}
}
} else {
info!("Bootstrap not complete - running full bootstrap...");
trace!(".env file not found, running bootstrap.bootstrap()...");
_ = bootstrap.bootstrap().await;
if let Err(e) = bootstrap.bootstrap().await {
error!("Bootstrap failed: {}", e);
return Err(std::io::Error::new(
std::io::ErrorKind::Other,
format!("Bootstrap failed: {}", e),
));
}
trace!("bootstrap.bootstrap() completed");
progress_tx_clone
.send(BootstrapProgress::StartingComponent(