torrust_tracker_deployer_lib/application/services/rendering/mod.rs
1//! Template Rendering Services
2//!
3//! This module contains application-layer services for rendering infrastructure
4//! templates. Each service encapsulates the logic for rendering a specific type
5//! of template (Ansible, `OpenTofu`, Docker Compose, etc.) and is designed to be
6//! shared across multiple command handlers and steps.
7//!
8//! ## Architecture
9//!
10//! Rendering services follow the DDD application layer pattern:
11//!
12//! - **Orchestrate**: Bridge multiple domain types into infrastructure generator calls
13//! - **Transform**: Map domain types to template-specific context types
14//! - **Decide**: Apply conditional logic (e.g., "if Prometheus is configured, include it")
15//!
16//! ## Services
17//!
18//! - `AnsibleTemplateRenderingService` - Renders Ansible inventory and playbook templates
19//! - `OpenTofuTemplateRenderingService` - Renders `OpenTofu` infrastructure templates
20//! - `TrackerTemplateRenderingService` - Renders Tracker configuration templates
21//! - `PrometheusTemplateRenderingService` - Renders Prometheus configuration templates
22//! - `GrafanaTemplateRenderingService` - Renders Grafana provisioning templates
23//! - `DockerComposeTemplateRenderingService` - Renders Docker Compose configuration templates
24//! - `CaddyTemplateRenderingService` - Renders Caddy TLS proxy configuration templates
25//! - `BackupTemplateRenderingService` - Renders backup configuration templates
26//!
27//! ## Design Principles
28//!
29//! All rendering services follow these principles:
30//!
31//! 1. **Explicit Inputs**: Services take explicit domain config types (e.g., `&TrackerConfig`)
32//! rather than `Environment<S>`. This makes dependencies clear and allows both the render
33//! command handler and the release steps to call them.
34//!
35//! 2. **Factory Pattern**: Services use `from_paths()` or `from_params()` factory methods
36//! that accept `templates_dir`, `build_dir`, and `clock` as construction parameters.
37//!
38//! 3. **Single Responsibility**: Each service handles exactly one template type and its
39//! associated context building logic.
40//!
41//! 4. **Error Wrapping**: Services define thin error types that wrap infrastructure
42//! generator errors while preserving context.
43//!
44//! ## Usage Example
45//!
46//! ```rust,ignore
47//! use std::sync::Arc;
48//! use torrust_tracker_deployer_lib::application::services::rendering::AnsibleTemplateRenderingService;
49//! use torrust_tracker_deployer_lib::shared::clock::SystemClock;
50//!
51//! let service = AnsibleTemplateRenderingService::from_paths(
52//! templates_dir,
53//! build_dir,
54//! Arc::new(SystemClock),
55//! );
56//!
57//! service.render_templates(&user_inputs, instance_ip, None).await?;
58//! ```
59
60mod ansible;
61mod backup;
62mod caddy;
63mod docker_compose;
64mod grafana;
65mod opentofu;
66mod prometheus;
67mod tracker;
68
69pub use ansible::{AnsibleTemplateRenderingService, AnsibleTemplateRenderingServiceError};
70pub use backup::{BackupTemplateRenderingService, BackupTemplateRenderingServiceError};
71pub use caddy::{CaddyTemplateRenderingService, CaddyTemplateRenderingServiceError};
72pub use docker_compose::{
73 DockerComposeTemplateRenderingService, DockerComposeTemplateRenderingServiceError,
74};
75pub use grafana::{GrafanaTemplateRenderingService, GrafanaTemplateRenderingServiceError};
76pub use opentofu::{OpenTofuTemplateRenderingService, OpenTofuTemplateRenderingServiceError};
77pub use prometheus::{PrometheusTemplateRenderingService, PrometheusTemplateRenderingServiceError};
78pub use tracker::{TrackerTemplateRenderingService, TrackerTemplateRenderingServiceError};