use super::LoaderOverrides;
use super::diagnostics::config_error_from_toml;
use super::diagnostics::io_error_from_config_error;
#[cfg(target_os = "macos")]
use super::macos::load_managed_admin_config_layer;
use crate::product::utils_absolute_path::AbsolutePathBuf;
use std::io;
use std::path::Path;
use std::path::PathBuf;
use tokio::fs;
use toml::Value as TomlValue;
#[cfg(unix)]
const LHA_MANAGED_CONFIG_SYSTEM_PATH: &str = "/etc/lha/managed_config.toml";
#[derive(Debug, Clone)]
pub(super) struct MangedConfigFromFile {
pub managed_config: TomlValue,
pub file: AbsolutePathBuf,
}
#[derive(Debug, Clone)]
pub(super) struct LoadedConfigLayers {
pub managed_config: Option<MangedConfigFromFile>,
pub managed_config_from_mdm: Option<TomlValue>,
}
pub(super) async fn load_config_layers_internal(
lha_home: &Path,
overrides: LoaderOverrides,
) -> io::Result<LoadedConfigLayers> {
#[cfg(target_os = "macos")]
let LoaderOverrides {
managed_config_path,
managed_preferences_base64,
..
} = overrides;
#[cfg(not(target_os = "macos"))]
let LoaderOverrides {
managed_config_path,
..
} = overrides;
let managed_config_path = AbsolutePathBuf::from_absolute_path(
managed_config_path.unwrap_or_else(|| managed_config_default_path(lha_home)),
)?;
let managed_config = read_config_from_path(&managed_config_path, false)
.await?
.map(|managed_config| MangedConfigFromFile {
managed_config,
file: managed_config_path.clone(),
});
#[cfg(target_os = "macos")]
let managed_preferences =
load_managed_admin_config_layer(managed_preferences_base64.as_deref()).await?;
#[cfg(not(target_os = "macos"))]
let managed_preferences = None;
Ok(LoadedConfigLayers {
managed_config,
managed_config_from_mdm: managed_preferences,
})
}
pub(super) async fn read_config_from_path(
path: impl AsRef<Path>,
log_missing_as_info: bool,
) -> io::Result<Option<TomlValue>> {
match fs::read_to_string(path.as_ref()).await {
Ok(contents) => match toml::from_str::<TomlValue>(&contents) {
Ok(value) => Ok(Some(value)),
Err(err) => {
tracing::error!("Failed to parse {}: {err}", path.as_ref().display());
let config_error = config_error_from_toml(path.as_ref(), &contents, err.clone());
Err(io_error_from_config_error(
io::ErrorKind::InvalidData,
config_error,
Some(err),
))
}
},
Err(err) if err.kind() == io::ErrorKind::NotFound => {
if log_missing_as_info {
tracing::info!("{} not found, using defaults", path.as_ref().display());
} else {
tracing::debug!("{} not found", path.as_ref().display());
}
Ok(None)
}
Err(err) => {
tracing::error!("Failed to read {}: {err}", path.as_ref().display());
Err(err)
}
}
}
pub(super) fn managed_config_default_path(lha_home: &Path) -> PathBuf {
#[cfg(unix)]
{
let _ = lha_home;
PathBuf::from(LHA_MANAGED_CONFIG_SYSTEM_PATH)
}
#[cfg(not(unix))]
{
lha_home.join("managed_config.toml")
}
}