pupoxide/lib.rs
1//! # Pupoxide
2//!
3//! A high-performance, memory-safe, declarative configuration management tool inspired by Puppet.
4//!
5//! Pupoxide leverages the power and safety of Rust and integrates the flexible scripting capabilities of Rhai
6//! to allow expressing complex system configurations cleanly, safely, and efficiently.
7//!
8//! ## Key Features
9//!
10//! - **Declarative Configuration DSL**: Describe files, directories, commands, and packages using a simple Rhai-based DSL.
11//! - **Safe Concurrent Execution**: Resources are executed in parallel using a Kahn-based topological sort, respecting dependency relationships.
12//! - **Resource Mutexes**: Package managers (like `apt` or `brew`) and other conflicting resources are automatically serialized using internal mutex locks.
13//! - **Hexagonal Architecture**: Core domains and applications are decoupled from infrastructure stores via clean ports and adapters.
14//! - **Hierarchical Configuration (Stash)**: Dynamically resolve system variables based on target host facts using a Multi-level Tera templated configuration storage.
15//! - **Zero Warnings & High Safety**: Built under a strict `#![deny(clippy::unwrap_used)]` compiler warning policy.
16//!
17//! ## Architecture Overview
18//!
19//! Pupoxide follows a clean **Ports & Adapters (Hexagonal)** architectural pattern inside `src/`:
20//!
21//! 1. **Domain (`src/domain/`)**: Houses the primary business entities (like `Resource`, `Catalog`, `Transaction`, `Facts`, and `ResourceReport`) and abstract port traits (like `ResourceProvider`). It is highly pure and contains minimal external dependencies.
22//! 2. **Application (`src/application/`)**: Defines orchestrations, including DSL registration, manifest evaluation via `PupoxideEngine`, and execution graphs via `execute_transaction`. It relies on abstract ports like `StashProvider` and `StateStore`.
23//! 3. **Infrastructure (`src/infrastructure/`)**: Implements specific I/O adapters, such as concrete `Stash` filesystems and transaction log `StateStore` adapters.
24//! 4. **Interface (`src/interface/`)**: Entry point for CLI configurations, REST handlers, or agent bindings.
25//!
26//! ## Quick Start Example
27//!
28//! The following example demonstrates how to configure the engine, compile a manifest, and apply it to a target system.
29//!
30//! ### 1. Write a Rhai Manifest (`site.rhai`)
31//!
32//! ```rhai
33//! // Declare a package resource
34//! pkg("git", #{
35//! ensure: "present",
36//! });
37//!
38//! // Create a custom configuration file depending on git
39//! file("/etc/myapp/config.yaml", #{
40//! ensure: "present",
41//! content: "port: 8080\nenvironment: production",
42//! require: ["package:git"],
43//! });
44//! ```
45//!
46//! ### 2. Execute via Rust API
47//!
48//! ```rust,ignore
49//! use pupoxide::application::{PupoxideEngine, execute_transaction};
50//! use pupoxide::domain::facts::Facts;
51//! use pupoxide::infrastructure::{Stash, StateStore, FsAdapter};
52//! use std::path::PathBuf;
53//! use std::sync::Arc;
54//!
55//! #[tokio::main]
56//! async fn main() -> anyhow::Result<()> {
57//! // 1. Gather host facts
58//! let mut facts = Facts::new();
59//! facts.insert("os_family".to_string(), "Darwin".to_string());
60//! facts.insert("hostname".to_string(), "my-macbook".to_string());
61//!
62//! // 2. Initialize Infrastructure Adapters
63//! let env_path = PathBuf::from("./examples/environments/production");
64//! let stash = Stash::new(env_path.clone())?.map(|s| Arc::new(s) as Arc<dyn pupoxide::application::StashProvider>);
65//! let state_store = StateStore::new(env_path.clone());
66//! let provider = Arc::new(FsAdapter::new());
67//!
68//! // 3. Build & Run the Pupoxide Engine
69//! let engine = PupoxideEngine::builder()
70//! .with_stash(stash.expect("stash config missing"))
71//! .with_module_path(env_path.join("modules"))
72//! .register_defaults()
73//! .build();
74//!
75//! let catalog = engine.run_manifest(
76//! env_path.join("manifests/site.rhai"),
77//! "my-macbook".to_string(),
78//! "production".to_string(),
79//! facts,
80//! )?;
81//!
82//! // 4. Apply configuration via Parallel Execution Graph
83//! let reports = execute_transaction(
84//! catalog,
85//! &state_store,
86//! provider,
87//! false, // dry_run
88//! |report| {
89//! println!("Resource [{}]: {:?}", report.resource_id, report.status);
90//! }
91//! ).await?;
92//!
93//! println!("Successfully synchronized system configuration!");
94//! Ok(())
95//! }
96//! ```
97
98#![deny(clippy::unwrap_used)]
99
100pub mod application;
101pub mod domain;
102pub mod infrastructure;
103pub mod interface;
104
105pub use domain::resource;
106pub use infrastructure::FsAdapter;