Skip to content
74 changes: 64 additions & 10 deletions src/infrastructure/external_tools/ansible/template/renderer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ use crate::infrastructure::external_tools::ansible::template::wrappers::inventor

pub mod firewall_playbook;
pub mod inventory;
pub mod variables;

pub use firewall_playbook::FirewallPlaybookTemplateRenderer;
pub use inventory::InventoryTemplateRenderer;
pub use variables::VariablesTemplateRenderer;

/// Errors that can occur during configuration template rendering
#[derive(Error, Debug)]
Expand Down Expand Up @@ -129,6 +131,20 @@ pub enum ConfigurationTemplateError {
#[source]
source: firewall_playbook::FirewallPlaybookTemplateError,
},

/// Failed to render variables template using collaborator
#[error("Failed to render variables template: {source}")]
VariablesRenderingFailed {
#[source]
source: variables::VariablesTemplateError,
},

/// Failed to create context from inventory data
#[error("Failed to create {context_type} context: {message}")]
ContextCreationFailed {
context_type: String,
message: String,
},
}

/// Renders `Ansible` configuration templates to a build directory
Expand All @@ -141,6 +157,7 @@ pub struct AnsibleTemplateRenderer {
template_manager: Arc<TemplateManager>,
inventory_renderer: InventoryTemplateRenderer,
firewall_playbook_renderer: FirewallPlaybookTemplateRenderer,
variables_renderer: VariablesTemplateRenderer,
}

impl AnsibleTemplateRenderer {
Expand All @@ -161,12 +178,14 @@ impl AnsibleTemplateRenderer {
let inventory_renderer = InventoryTemplateRenderer::new(template_manager.clone());
let firewall_playbook_renderer =
FirewallPlaybookTemplateRenderer::new(template_manager.clone());
let variables_renderer = VariablesTemplateRenderer::new(template_manager.clone());

Self {
build_dir: build_dir.as_ref().to_path_buf(),
template_manager,
inventory_renderer,
firewall_playbook_renderer,
variables_renderer,
}
}

Expand Down Expand Up @@ -219,6 +238,12 @@ impl AnsibleTemplateRenderer {
|source| ConfigurationTemplateError::FirewallPlaybookRenderingFailed { source },
)?;

// Render dynamic variables template with system configuration using collaborator
let variables_context = Self::create_variables_context(inventory_context)?;
self.variables_renderer
.render(&variables_context, &build_ansible_dir)
.map_err(|source| ConfigurationTemplateError::VariablesRenderingFailed { source })?;

// Copy static Ansible files (config and playbooks)
self.copy_static_templates(&self.template_manager, &build_ansible_dir)
.await?;
Expand Down Expand Up @@ -421,21 +446,50 @@ impl AnsibleTemplateRenderer {

// Extract SSH port from inventory context
let ssh_port = AnsiblePort::new(inventory_context.ansible_port()).map_err(|e| {
ConfigurationTemplateError::TemplatePathFailed {
file_name: "configure-firewall.yml.tera".to_string(),
source: TemplateManagerError::TemplateNotFound {
relative_path: format!("Invalid SSH port: {e}"),
},
ConfigurationTemplateError::ContextCreationFailed {
context_type: "FirewallPlaybook".to_string(),
message: format!("Invalid SSH port: {e}"),
}
})?;

// Create firewall context
FirewallPlaybookContext::new(ssh_port).map_err(|e| {
ConfigurationTemplateError::TemplatePathFailed {
file_name: "configure-firewall.yml.tera".to_string(),
source: TemplateManagerError::TemplateNotFound {
relative_path: format!("Failed to create firewall context: {e}"),
},
ConfigurationTemplateError::ContextCreationFailed {
context_type: "FirewallPlaybook".to_string(),
message: format!("Failed to create firewall context: {e}"),
}
})
}

/// Creates an `AnsibleVariablesContext` from an `InventoryContext`
///
/// Extracts the SSH port from the inventory context to create
/// a variables context for template rendering.
///
/// # Arguments
///
/// * `inventory_context` - The inventory context containing SSH port information
///
/// # Returns
///
/// * `Result<AnsibleVariablesContext, ConfigurationTemplateError>` - The variables context or an error
///
/// # Errors
///
/// Returns an error if the SSH port cannot be extracted or validated
fn create_variables_context(
inventory_context: &InventoryContext,
) -> Result<
crate::infrastructure::external_tools::ansible::template::wrappers::variables::AnsibleVariablesContext,
ConfigurationTemplateError,
>{
use crate::infrastructure::external_tools::ansible::template::wrappers::variables::AnsibleVariablesContext;

// Extract SSH port from inventory context and create variables context
AnsibleVariablesContext::new(inventory_context.ansible_port()).map_err(|e| {
ConfigurationTemplateError::ContextCreationFailed {
context_type: "AnsibleVariables".to_string(),
message: format!("Failed to create variables context: {e}"),
}
})
}
Expand Down
Loading