158 lines
4.6 KiB
Rust
158 lines
4.6 KiB
Rust
//! Provisioning Platform Daemon
|
|
//!
|
|
//! A thin wrapper around daemon-cli library with provisioning-specific
|
|
//! configuration. All core functionality (Nushell execution, config rendering,
|
|
//! i18n) is provided by daemon-cli.
|
|
|
|
mod config;
|
|
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use axum::Router;
|
|
use clap::Parser;
|
|
use config::ProvisioningDaemonConfigWrapper;
|
|
use daemon_cli::{
|
|
api::api_routes,
|
|
core::{DaemonConfig, HierarchicalCache, Result},
|
|
orchestration::{
|
|
AuditOperation, EncryptOperation, InitServsOperation, OperationRegistry, RuntimeOperation,
|
|
ValidaOperation,
|
|
},
|
|
AppState,
|
|
};
|
|
use tokio::net::TcpListener;
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
/// Provisioning daemon - Nushell execution and configuration rendering service
|
|
#[derive(Parser, Debug)]
|
|
#[command(name = "provisioning-daemon")]
|
|
#[command(about = "Provisioning platform daemon with Nushell execution and config rendering")]
|
|
#[command(version = env!("CARGO_PKG_VERSION"))]
|
|
struct Args {
|
|
/// Configuration file path (highest priority)
|
|
#[arg(short = 'c', long, env = "PROVISIONING_DAEMON_CONFIG")]
|
|
config: Option<PathBuf>,
|
|
|
|
/// Configuration directory (searches for provisioning-daemon.ncl|toml|json)
|
|
#[arg(long, env = "PROVISIONING_CONFIG_DIR")]
|
|
config_dir: Option<PathBuf>,
|
|
|
|
/// Deployment mode (solo, multiuser, cicd, enterprise)
|
|
#[arg(short = 'm', long, env = "PROVISIONING_DAEMON_MODE")]
|
|
mode: Option<String>,
|
|
|
|
/// Enable verbose logging
|
|
#[arg(short = 'v', long)]
|
|
verbose: bool,
|
|
|
|
/// Validate configuration and exit
|
|
#[arg(long)]
|
|
validate_config: bool,
|
|
|
|
/// Show configuration and exit
|
|
#[arg(long)]
|
|
show_config: bool,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
let args = Args::parse();
|
|
|
|
// Initialize logging
|
|
let log_level = if args.verbose { "debug" } else { "info" };
|
|
let filter = EnvFilter::new(format!(
|
|
"provisioning_daemon={},tower_http=info,daemon_cli=info",
|
|
log_level
|
|
));
|
|
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(filter)
|
|
.with_target(false)
|
|
.init();
|
|
|
|
tracing::info!(
|
|
"Starting Provisioning Daemon v{}",
|
|
env!("CARGO_PKG_VERSION")
|
|
);
|
|
|
|
// Load configuration with hierarchical support
|
|
let config_wrapper = if let Some(explicit_path) = args.config {
|
|
// Use explicit path from CLI argument
|
|
ProvisioningDaemonConfigWrapper {
|
|
config_path: explicit_path,
|
|
}
|
|
} else {
|
|
// Use hierarchical loading (env vars or defaults)
|
|
ProvisioningDaemonConfigWrapper::load_from_hierarchy()
|
|
};
|
|
|
|
tracing::debug!("Loading configuration from: {}", config_wrapper.path_str());
|
|
|
|
// Load configuration using external daemon library
|
|
let config = DaemonConfig::load(Some(config_wrapper.path().clone()))?;
|
|
|
|
// Handle special commands
|
|
if args.validate_config {
|
|
config.validate()?;
|
|
println!("✓ Configuration is valid");
|
|
return Ok(());
|
|
}
|
|
|
|
if args.show_config {
|
|
config.print();
|
|
return Ok(());
|
|
}
|
|
|
|
// Validate configuration
|
|
config.validate()?;
|
|
tracing::info!("Configuration validated: bind={}", config.server.bind);
|
|
|
|
// Create cache system
|
|
let cache = HierarchicalCache::new()?;
|
|
let cache_arc = Arc::new(cache);
|
|
|
|
// Create operation registry
|
|
let mut registry = OperationRegistry::default();
|
|
registry.register("valida", Arc::new(ValidaOperation::new(cache_arc.clone())));
|
|
registry.register(
|
|
"runtime",
|
|
Arc::new(RuntimeOperation::new(cache_arc.clone())),
|
|
);
|
|
registry.register(
|
|
"encrypt",
|
|
Arc::new(EncryptOperation::new(cache_arc.clone())),
|
|
);
|
|
registry.register(
|
|
"init-servs",
|
|
Arc::new(InitServsOperation::new(cache_arc.clone())),
|
|
);
|
|
registry.register("audit", Arc::new(AuditOperation::new(cache_arc.clone())));
|
|
|
|
tracing::info!(
|
|
"✓ Registered {} operations: {}",
|
|
registry.len(),
|
|
registry.list().join(", ")
|
|
);
|
|
|
|
// Create app state
|
|
let state = AppState::new(config.clone(), cache_arc, registry);
|
|
|
|
// Create router
|
|
let app = Router::new().nest("/api/v1", api_routes(state.clone()));
|
|
|
|
// Start server
|
|
let addr = config.bind_addr()?;
|
|
let listener = TcpListener::bind(addr).await?;
|
|
|
|
tracing::info!("✓ Provisioning daemon listening on http://{}", addr);
|
|
tracing::info!("API documentation: http://{}/api/v1/health", addr);
|
|
tracing::info!("Config rendering: http://{}/api/v1/render", addr);
|
|
tracing::info!("i18n translation: http://{}/api/v1/translate", addr);
|
|
|
|
// Run server
|
|
axum::serve(listener, app).await?;
|
|
|
|
Ok(())
|
|
}
|