use anyhow::Result;
use crate::node::Node;
use super::types::{Cluster, Config, NodeConfig};
use super::utils::{expand_env_vars, get_current_username};
impl Config {
pub fn get_cluster(&self, name: &str) -> Option<&Cluster> {
self.clusters.get(name)
}
pub fn resolve_nodes(&self, cluster_name: &str) -> Result<Vec<Node>> {
let cluster = self
.get_cluster(cluster_name)
.ok_or_else(|| anyhow::anyhow!("Cluster '{}' not found in configuration.\nAvailable clusters: {}\nPlease check your configuration file or use 'bssh list' to see available clusters.", cluster_name, self.clusters.keys().cloned().collect::<Vec<_>>().join(", ")))?;
let mut nodes = Vec::new();
for node_config in &cluster.nodes {
let node = match node_config {
NodeConfig::Simple(host) => {
let expanded_host = expand_env_vars(host);
let default_user = cluster
.defaults
.user
.as_ref()
.or(self.defaults.user.as_ref())
.map(|u| expand_env_vars(u));
let default_port = cluster.defaults.port.or(self.defaults.port).unwrap_or(22);
Node::parse(&expanded_host, default_user.as_deref()).map(|mut n| {
if !expanded_host.contains(':') {
n.port = default_port;
}
n
})?
}
NodeConfig::Detailed { host, port, user } => {
let expanded_host = expand_env_vars(host);
let username = user
.as_ref()
.map(|u| expand_env_vars(u))
.or_else(|| cluster.defaults.user.as_ref().map(|u| expand_env_vars(u)))
.or_else(|| self.defaults.user.as_ref().map(|u| expand_env_vars(u)))
.unwrap_or_else(get_current_username);
let port = port
.or(cluster.defaults.port)
.or(self.defaults.port)
.unwrap_or(22);
Node::new(expanded_host, port, username)
}
};
nodes.push(node);
}
Ok(nodes)
}
pub fn get_ssh_key(&self, cluster_name: Option<&str>) -> Option<String> {
if let Some(cluster_name) = cluster_name {
if let Some(cluster) = self.get_cluster(cluster_name) {
if let Some(key) = &cluster.defaults.ssh_key {
return Some(key.clone());
}
}
}
self.defaults.ssh_key.clone()
}
pub fn get_timeout(&self, cluster_name: Option<&str>) -> Option<u64> {
if let Some(cluster_name) = cluster_name {
if let Some(cluster) = self.get_cluster(cluster_name) {
if let Some(timeout) = cluster.defaults.timeout {
return Some(timeout);
}
}
}
self.defaults.timeout
}
pub fn get_parallel(&self, cluster_name: Option<&str>) -> Option<usize> {
if let Some(cluster_name) = cluster_name {
if let Some(cluster) = self.get_cluster(cluster_name) {
if let Some(parallel) = cluster.defaults.parallel {
return Some(parallel);
}
}
}
self.defaults.parallel
}
}