kaji 0.0.1

Steer your Keycloak configuration to a stable, declared state.
Documentation
use crate::client::KeycloakClient;
use crate::models::RealmRepresentation;
use crate::utils::secrets::{SecretResolver, substitute_secrets};
use crate::utils::ui::SUCCESS_UPDATE;
use crate::utils::yaml::load_yaml_with_overlay;
use anyhow::{Context, Result};
use console::style;
use std::collections::HashSet;
use std::path::PathBuf;
use std::sync::Arc;
use tokio::fs as async_fs;

pub async fn apply_realm(
    client: &KeycloakClient,
    workspace_dir: &std::path::Path,
    resolver: Arc<dyn SecretResolver>,
    planned_files: Arc<Option<HashSet<PathBuf>>>,
    realm_name: &str,
    profile: Option<String>,
) -> Result<()> {
    // 1. Apply Realm
    let realm_path = workspace_dir.join("realm.yaml");
    if let Some(plan) = &*planned_files
        && !plan.contains(&realm_path)
    {
        return Ok(());
    }
    if async_fs::try_exists(&realm_path).await? {
        let mut val = load_yaml_with_overlay(&realm_path, profile.as_deref()).await?;
        substitute_secrets(&mut val, Arc::clone(&resolver)).await?;
        let realm_rep: RealmRepresentation = serde_json::from_value(val)?;
        client
            .update_realm(&realm_rep)
            .await
            .with_context(|| format!("Failed to update realm '{}'", realm_name))?;
        println!(
            "  {} {}",
            SUCCESS_UPDATE,
            style("Updated realm configuration").cyan()
        );
    }
    Ok(())
}