use std::collections::HashMap;
use crate::util::yaml::blend_variables;
use std::sync::Arc;
use crate::inventory::hosts::Host;
use std::sync::RwLock;
use serde_yaml;
pub struct Group {
pub name : String,
pub subgroups : HashMap<String, Arc<RwLock<Self>>>,
pub parents : HashMap<String, Arc<RwLock<Self>>>,
pub hosts : HashMap<String, Arc<RwLock<Host>>>,
pub variables : serde_yaml::Mapping,
dyn_variables : serde_yaml::Value,
}
impl Group {
pub fn new(name: &String) -> Self {
Self {
name : name.clone(),
subgroups : HashMap::new(),
parents : HashMap::new(),
hosts : HashMap::new(),
variables : serde_yaml::Mapping::new(),
dyn_variables: serde_yaml::Value::from(serde_yaml::Mapping::new()),
}
}
pub fn add_subgroup(&mut self, name: &String, subgroup: Arc<RwLock<Group>>) {
assert!(!name.eq(&self.name));
self.subgroups.insert(
name.clone(),
Arc::clone(&subgroup)
);
}
pub fn add_host(&mut self, name: &String, host: Arc<RwLock<Host>>) {
self.hosts.insert(
name.clone(),
Arc::clone(&host)
);
}
pub fn add_parent(&mut self, name: &String, parent: Arc<RwLock<Group>>) {
assert!(!name.eq(&self.name));
self.parents.insert(
name.clone(),
Arc::clone(&parent)
);
}
pub fn get_ancestor_groups(&self, depth_limit: usize) -> HashMap<String, Arc<RwLock<Group>>> {
let mut results : HashMap<String, Arc<RwLock<Group>>> = HashMap::new();
for (k,v) in self.parents.iter() {
results.insert(k.clone(), Arc::clone(v));
if depth_limit > 0 {
for (k2,v2) in v.read().expect("group read").get_ancestor_groups(depth_limit-1) {
results.insert(k2.clone(),Arc::clone(&v2));
}
}
}
return results
}
pub fn get_ancestor_group_names(&self) -> Vec<String> {
return self.get_ancestor_groups(10usize).iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_descendant_groups(&self, depth_limit: usize) -> HashMap<String, Arc<RwLock<Group>>> {
let mut results : HashMap<String, Arc<RwLock<Group>>> = HashMap::new();
for (k,v) in self.subgroups.iter() {
if results.contains_key(&k.clone()) {
continue;
}
if depth_limit > 0 {
for (k2,v2) in v.read().expect("group read").get_descendant_groups(depth_limit-1).iter() {
results.insert(
k2.clone(),
Arc::clone(&v2)
);
}
}
results.insert(
k.clone(),
Arc::clone(&v)
);
}
return results
}
pub fn get_descendant_group_names(&self) -> Vec<String> {
return self.get_descendant_groups(10usize).iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_parent_groups(&self) -> HashMap<String, Arc<RwLock<Group>>> {
let mut results : HashMap<String, Arc<RwLock<Group>>> = HashMap::new();
for (k,v) in self.parents.iter() {
results.insert(
k.clone(),
Arc::clone(&v)
);
}
return results
}
pub fn get_parent_group_names(&self) -> Vec<String> {
return self.get_parent_groups().iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_subgroups(&self) -> HashMap<String, Arc<RwLock<Group>>> {
let mut results : HashMap<String, Arc<RwLock<Group>>> = HashMap::new();
for (k,v) in self.subgroups.iter() {
results.insert(
k.clone(),
Arc::clone(&v)
);
}
return results
}
pub fn get_subgroup_names(&self) -> Vec<String> {
return self.get_subgroups().iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_direct_hosts(&self) -> HashMap<String, Arc<RwLock<Host>>> {
let mut results : HashMap<String, Arc<RwLock<Host>>> = HashMap::new();
for (k,v) in self.hosts.iter() {
results.insert(
k.clone(),
Arc::clone(&v)
);
}
return results
}
pub fn get_direct_host_names(&self) -> Vec<String> {
return self.get_direct_hosts().iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_descendant_hosts(&self) -> HashMap<String, Arc<RwLock<Host>>> {
let mut results : HashMap<String, Arc<RwLock<Host>>> = HashMap::new();
let children = self.get_direct_hosts();
for (k,v) in children { results.insert(k.clone(), Arc::clone(&v)); }
let groups = self.get_descendant_groups(20usize);
for (_k,v) in groups.iter() {
let hosts = v.read().unwrap().get_direct_hosts();
for (k2,v2) in hosts.iter() { results.insert(k2.clone(), Arc::clone(&v2)); }
}
return results
}
pub fn get_descendant_host_names(&self) -> Vec<String> {
return self.get_descendant_hosts().iter().map(|(k,_v)| k.clone()).collect();
}
pub fn get_variables(&self) -> serde_yaml::Mapping {
return self.variables.clone();
}
pub fn set_variables(&mut self, variables: serde_yaml::Mapping) {
self.variables = variables.clone();
}
pub fn update_variables(&mut self, mapping: serde_yaml::Mapping) {
let map = mapping.clone();
blend_variables(&mut self.dyn_variables, serde_yaml::Value::Mapping(map));
}
pub fn get_blended_variables(&self) -> serde_yaml::Mapping {
let mut blended : serde_yaml::Value = serde_yaml::Value::from(serde_yaml::Mapping::new());
let ancestors = self.get_ancestor_groups(20);
for (_k,v) in ancestors.iter() {
let theirs : serde_yaml::Value = serde_yaml::Value::from(v.read().expect("group read").get_variables());
blend_variables(&mut blended, theirs);
}
blend_variables(&mut blended, self.dyn_variables.clone());
let mine = serde_yaml::Value::from(self.get_variables());
blend_variables(&mut blended, mine);
return match blended {
serde_yaml::Value::Mapping(x) => x,
_ => panic!("get_blended_variables produced a non-mapping (1)")
}
}
pub fn get_variables_yaml(&self) -> Result<String,String> {
let result = serde_yaml::to_string(&self.get_variables());
return match result {
Ok(x) => Ok(x),
Err(_y) => Err(String::from("error loading variables"))
}
}
pub fn get_blended_variables_yaml(&self) -> Result<String,String> {
let result = serde_yaml::to_string(&self.get_blended_variables());
return match result {
Ok(x) => Ok(x),
Err(_y) => Err(String::from("error loading blended variables"))
}
}
}