2022-04-20 16:15:38 +00:00
|
|
|
use log::debug;
|
2021-08-06 17:58:40 +00:00
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use snafu::ResultExt;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::fs;
|
|
|
|
|
2022-04-20 16:07:32 +00:00
|
|
|
use crate::constants::{HARDWARE_CONFIG_FILE, SERVICES};
|
2021-08-06 17:58:40 +00:00
|
|
|
use crate::error::{FileReadError, FileWriteError, PeachConfigError};
|
|
|
|
use crate::utils::get_output;
|
|
|
|
use crate::RtcOption;
|
|
|
|
|
2022-04-20 16:07:32 +00:00
|
|
|
pub fn get_package_version_number(package: &str) -> Result<String, PeachConfigError> {
|
|
|
|
let version = get_output(&["dpkg-query", "--showformat='${Version}'", "--show", package])?;
|
|
|
|
debug!("version: {:?}", version);
|
|
|
|
Ok(version)
|
|
|
|
}
|
|
|
|
|
2021-08-06 17:58:40 +00:00
|
|
|
/// Returns a HashMap<String, String> of all the peach-packages which are currently installed
|
|
|
|
/// mapped to their version number e.g. { "peach-probe": "1.2.0", "peach-network": "1.4.0" }
|
|
|
|
pub fn get_currently_installed_microservices() -> Result<HashMap<String, String>, PeachConfigError>
|
|
|
|
{
|
2022-04-20 16:07:32 +00:00
|
|
|
// gets a list of all packages currently installed with dpkg-query
|
2022-04-20 16:15:38 +00:00
|
|
|
let peach_packages: HashMap<String, String> = SERVICES
|
|
|
|
.iter()
|
|
|
|
.filter_map(|service| {
|
|
|
|
let version = get_package_version_number(service);
|
|
|
|
match version {
|
|
|
|
Ok(v) => Some((service.to_string(), v)),
|
|
|
|
Err(_) => None,
|
2021-08-06 17:58:40 +00:00
|
|
|
}
|
2022-04-20 16:15:38 +00:00
|
|
|
})
|
|
|
|
.collect();
|
2021-08-06 17:58:40 +00:00
|
|
|
|
|
|
|
// finally the hashmap of packages and version numbers is returned
|
|
|
|
Ok(peach_packages)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Output form of manifest
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
pub struct Manifest {
|
|
|
|
// packages is a map of {package_name: version}
|
|
|
|
packages: HashMap<String, String>,
|
|
|
|
hardware: Option<HardwareConfig>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The form that hardware configs are saved in when peach-config setup runs successfully
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
pub struct HardwareConfig {
|
|
|
|
// packages is a map of {package_name: version}
|
|
|
|
i2c: bool,
|
|
|
|
rtc: Option<RtcOption>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Log which hardware settings were configured to a .json file
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `i2c` - a boolean flag, if true i2c will be configured
|
|
|
|
/// * `rtc` - an optional enum, if supplied indicates which real-time-clock model
|
|
|
|
/// is being used
|
|
|
|
///
|
|
|
|
/// Any error results in a PeachConfigError, otherwise the saved HardwareConfig object
|
|
|
|
/// is returned.
|
|
|
|
pub fn save_hardware_config(
|
|
|
|
i2c: bool,
|
|
|
|
rtc: Option<RtcOption>,
|
|
|
|
) -> Result<HardwareConfig, PeachConfigError> {
|
|
|
|
let hardware_config = HardwareConfig { i2c, rtc };
|
|
|
|
|
|
|
|
let json_str = serde_json::to_string(&hardware_config)?;
|
|
|
|
|
|
|
|
fs::write(HARDWARE_CONFIG_FILE, json_str).context(FileWriteError {
|
|
|
|
file: HARDWARE_CONFIG_FILE.to_string(),
|
|
|
|
})?;
|
|
|
|
|
|
|
|
Ok(hardware_config)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Load the hardware configs that were saved from the last successful run of peach-config setup
|
|
|
|
///
|
|
|
|
/// Returns an Ok(Some<HardwareConfg>) containing the configuration if one is found,
|
|
|
|
/// and returns Ok(None) if no hardware configuration was found.
|
|
|
|
fn load_hardware_config() -> Result<Option<HardwareConfig>, PeachConfigError> {
|
|
|
|
// if there is no hardware_config, return None
|
|
|
|
let hardware_config_exists = std::path::Path::new(HARDWARE_CONFIG_FILE).exists();
|
|
|
|
if !hardware_config_exists {
|
|
|
|
Ok(None)
|
|
|
|
}
|
|
|
|
// otherwise we load hardware_config from json
|
|
|
|
else {
|
|
|
|
let contents = fs::read_to_string(HARDWARE_CONFIG_FILE).context(FileReadError {
|
|
|
|
file: HARDWARE_CONFIG_FILE.to_string(),
|
|
|
|
})?;
|
|
|
|
let hardware_config: HardwareConfig = serde_json::from_str(&contents)?;
|
|
|
|
Ok(Some(hardware_config))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Outputs a Manifest in json form to stdout
|
|
|
|
/// which contains the currently installed peach packages
|
|
|
|
/// as well as the hardware configuration of the last run of peach-config setup.
|
|
|
|
pub fn generate_manifest() -> Result<(), PeachConfigError> {
|
|
|
|
let packages = get_currently_installed_microservices()?;
|
|
|
|
let hardware_config_option = load_hardware_config()?;
|
|
|
|
let manifest = Manifest {
|
|
|
|
packages,
|
|
|
|
hardware: hardware_config_option,
|
|
|
|
};
|
|
|
|
let output = serde_json::to_string(&manifest)?;
|
|
|
|
println!("{}", output);
|
|
|
|
Ok(())
|
|
|
|
}
|