use std::collections::HashMap;
use crate::composer::types::ComposerResult;
pub struct ProfilesHandler {
system_env: HashMap<String, String>,
env_file_vars: HashMap<String, String>,
}
impl Default for ProfilesHandler {
fn default() -> Self {
Self::new()
}
}
impl ProfilesHandler {
pub fn new() -> Self {
Self {
system_env: std::env::vars().collect(),
env_file_vars: HashMap::new(),
}
}
pub fn with_system_env(system_env: HashMap<String, String>) -> Self {
Self {
system_env,
env_file_vars: HashMap::new(),
}
}
pub fn set_env_file_vars(&mut self, env_vars: &HashMap<String, String>) {
self.env_file_vars = env_vars.clone();
}
pub fn get_active_profiles(&self) -> Vec<String> {
self.get_compose_profiles_value()
.unwrap_or_default()
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect()
}
pub fn get_compose_profiles_value(&self) -> Option<String> {
if let Some(value) = self.system_env.get("COMPOSE_PROFILES") {
return Some(value.clone());
}
if let Some(value) = self.env_file_vars.get("COMPOSE_PROFILES") {
return Some(value.clone());
}
None
}
pub fn validate_profiles(
&self,
available_profiles: &[String],
) -> ComposerResult<ProfileValidationResult> {
let active_profiles = self.get_active_profiles();
let mut result = ProfileValidationResult::new();
result.active_profiles = active_profiles.clone();
result.available_profiles = available_profiles.to_vec();
for profile in &active_profiles {
if !available_profiles.contains(profile) {
result.invalid_profiles.push(profile.clone());
}
}
Ok(result)
}
pub fn should_include_in_env_dcd(&self, available_profiles: &[String]) -> bool {
if let Some(profiles_value) = self.get_compose_profiles_value() {
let active_profiles: Vec<String> = profiles_value
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect();
active_profiles
.iter()
.all(|profile| available_profiles.contains(profile))
} else {
false
}
}
pub fn get_env_dcd_value(&self, available_profiles: &[String]) -> Option<String> {
if self.should_include_in_env_dcd(available_profiles) {
self.get_compose_profiles_value()
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct ProfileValidationResult {
pub active_profiles: Vec<String>,
pub available_profiles: Vec<String>,
pub invalid_profiles: Vec<String>,
}
impl Default for ProfileValidationResult {
fn default() -> Self {
Self::new()
}
}
impl ProfileValidationResult {
pub fn new() -> Self {
Self {
active_profiles: Vec::new(),
available_profiles: Vec::new(),
invalid_profiles: Vec::new(),
}
}
pub fn is_valid(&self) -> bool {
self.invalid_profiles.is_empty()
}
pub fn has_active_profiles(&self) -> bool {
!self.active_profiles.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_active_profiles_from_system_env() {
let mut system_env = HashMap::new();
system_env.insert("COMPOSE_PROFILES".to_string(), "dev,test".to_string());
let handler = ProfilesHandler::with_system_env(system_env);
let profiles = handler.get_active_profiles();
assert_eq!(profiles, vec!["dev", "test"]);
}
#[test]
fn test_get_active_profiles_from_env_file() {
let mut env_vars = HashMap::new();
env_vars.insert("COMPOSE_PROFILES".to_string(), "prod,staging".to_string());
let mut handler = ProfilesHandler::with_system_env(HashMap::new());
handler.set_env_file_vars(&env_vars);
let profiles = handler.get_active_profiles();
assert_eq!(profiles, vec!["prod", "staging"]);
}
#[test]
fn test_validate_profiles_valid() {
let mut env_vars = HashMap::new();
env_vars.insert("COMPOSE_PROFILES".to_string(), "dev,test".to_string());
let mut handler = ProfilesHandler::with_system_env(HashMap::new());
handler.set_env_file_vars(&env_vars);
let available = vec!["dev".to_string(), "test".to_string(), "prod".to_string()];
let result = handler.validate_profiles(&available).unwrap();
assert!(result.is_valid());
assert_eq!(result.active_profiles, vec!["dev", "test"]);
assert!(result.invalid_profiles.is_empty());
}
#[test]
fn test_validate_profiles_invalid() {
let mut env_vars = HashMap::new();
env_vars.insert("COMPOSE_PROFILES".to_string(), "dev,invalid".to_string());
let mut handler = ProfilesHandler::with_system_env(HashMap::new());
handler.set_env_file_vars(&env_vars);
let available = vec!["dev".to_string(), "test".to_string()];
let result = handler.validate_profiles(&available).unwrap();
assert!(!result.is_valid());
assert_eq!(result.invalid_profiles, vec!["invalid"]);
}
#[test]
fn test_should_include_in_env_dcd() {
let mut env_vars = HashMap::new();
env_vars.insert("COMPOSE_PROFILES".to_string(), "dev,test".to_string());
let mut handler = ProfilesHandler::with_system_env(HashMap::new());
handler.set_env_file_vars(&env_vars);
let available = vec!["dev".to_string(), "test".to_string(), "prod".to_string()];
assert!(handler.should_include_in_env_dcd(&available));
let limited_available = vec!["dev".to_string()];
assert!(!handler.should_include_in_env_dcd(&limited_available));
}
}