diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 31afef3f68..58e6b3c429 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -47,10 +47,7 @@ pub async fn run(client: BaseHTTPClient, subcommand: LogsCommands) -> anyhow::Re // feed internal options structure by what was received from user // for now we always use / add defaults if any let dst_file = parse_destination(destination)?; - let result = client - .store(dst_file.as_path()) - .await - .map_err(|e| anyhow::Error::new(e))?; + let result = client.store(dst_file.as_path()).await?; println!("{}", result.clone().display()); @@ -83,9 +80,9 @@ pub async fn run(client: BaseHTTPClient, subcommand: LogsCommands) -> anyhow::Re /// * destination /// - if None then a default is returned /// - if a path to a directory then a default file name for the archive will be appended to the -/// path +/// path /// - if path with a file name then it is used as is for resulting archive, just extension will -/// be appended later on (depends on used compression) +/// be appended later on (depends on used compression) fn parse_destination(destination: Option) -> Result { let err = io::Error::new(io::ErrorKind::InvalidInput, "Invalid destination path"); let mut buffer = destination.unwrap_or(PathBuf::from(format!( diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index abe13305f8..1e7018cdac 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -87,17 +87,12 @@ fn validate(path: &PathBuf) -> anyhow::Result<()> { .context(format!("Could not validate the profile {:?}", path))?; match result { ValidationResult::Valid => { - println!( - "{} {}", - style("\u{2713}").bold().green(), - "The profile is valid." - ); + println!("{} The profile is valid.", style("\u{2713}").bold().green(),); } ValidationResult::NotValid(errors) => { eprintln!( - "{} {}", + "{} The profile is not valid. Please, check the following errors:\n", style("\u{2717}").bold().red(), - "The profile is not valid. Please, check the following errors:\n" ); for error in errors { println!("\t* {error}") diff --git a/rust/agama-lib/src/lib.rs b/rust/agama-lib/src/lib.rs index d767bef78f..a2213c2cad 100644 --- a/rust/agama-lib/src/lib.rs +++ b/rust/agama-lib/src/lib.rs @@ -35,11 +35,11 @@ //! Each of those modules contains, at least: //! //! * A settings model: it is a representation of the installation settings for the given topic. It -//! is expected to implement the [serde::Serialize], [serde::Deserialize] and -//! [agama_settings::settings::Settings] traits. +//! is expected to implement the [serde::Serialize], [serde::Deserialize] and +//! [agama_settings::settings::Settings] traits. //! * A store: it is the responsible for reading/writing the settings to the service. Usually, it -//! relies on a D-Bus client for communicating with the service, although it could implement that -//! logic itself. Note: we are considering defining a trait for stores too. +//! relies on a D-Bus client for communicating with the service, although it could implement that +//! logic itself. Note: we are considering defining a trait for stores too. //! //! As said, those modules might implement additional stuff, like specific types, clients, etc. diff --git a/rust/agama-lib/src/logs.rs b/rust/agama-lib/src/logs.rs index 8d1c2e029b..3b6c66e485 100644 --- a/rust/agama-lib/src/logs.rs +++ b/rust/agama-lib/src/logs.rs @@ -178,12 +178,12 @@ impl LogItem for LogCmd { .args(cmd_parts[1..].iter()) .output()?; - if output.stdout.len() > 0 { + if !output.stdout.is_empty() { let mut file_stdout = File::create(format!("{}.out.log", file_path.display()))?; file_stdout.write_all(&output.stdout)?; } - if output.stderr.len() > 0 { + if !output.stderr.is_empty() { let mut file_stderr = File::create(format!("{}.err.log", file_path.display()))?; file_stderr.write_all(&output.stderr)?; diff --git a/rust/agama-lib/src/manager/http_client.rs b/rust/agama-lib/src/manager/http_client.rs index c994f0500f..269ecc006f 100644 --- a/rust/agama-lib/src/manager/http_client.rs +++ b/rust/agama-lib/src/manager/http_client.rs @@ -83,7 +83,7 @@ impl ManagerHTTPClient { /// Asks backend for lists of log files and commands used for creating logs archive returned by /// store (/logs/store) backed HTTP API command pub async fn list(&self) -> Result { - Ok(self.client.get("/manager/logs/list").await?) + self.client.get("/manager/logs/list").await } /// Returns the installer status. diff --git a/rust/agama-lib/src/proxies/questions.rs b/rust/agama-lib/src/proxies/questions.rs index 7fb3d9ff58..97d74f7517 100644 --- a/rust/agama-lib/src/proxies/questions.rs +++ b/rust/agama-lib/src/proxies/questions.rs @@ -18,8 +18,8 @@ // To contact SUSE LLC about this file by physical or electronic mail, you may // find current contact information at www.suse.com. -mod questions; -pub use questions::QuestionsProxy; +mod base; +pub use base::QuestionsProxy; mod generic; pub use generic::GenericProxy as GenericQuestionProxy; diff --git a/rust/agama-lib/src/proxies/questions/questions.rs b/rust/agama-lib/src/proxies/questions/base.rs similarity index 100% rename from rust/agama-lib/src/proxies/questions/questions.rs rename to rust/agama-lib/src/proxies/questions/base.rs diff --git a/rust/agama-lib/src/scripts/model.rs b/rust/agama-lib/src/scripts/model.rs index 0fe8db8320..ddf3c651f2 100644 --- a/rust/agama-lib/src/scripts/model.rs +++ b/rust/agama-lib/src/scripts/model.rs @@ -53,7 +53,7 @@ pub struct BaseScript { impl BaseScript { fn write>(&self, workdir: P) -> Result<(), ScriptError> { let script_path = workdir.as_ref().join(&self.name); - std::fs::create_dir_all(&script_path.parent().unwrap())?; + std::fs::create_dir_all(script_path.parent().unwrap())?; let mut file = fs::OpenOptions::new() .create(true) @@ -109,7 +109,7 @@ impl Script { /// /// The name of the script depends on the work directory and the script's group. pub fn write>(&self, workdir: P) -> Result<(), ScriptError> { - let path = workdir.as_ref().join(&self.group().to_string()); + let path = workdir.as_ref().join(self.group().to_string()); self.base().write(&path) } @@ -145,7 +145,7 @@ impl Script { return Ok(()); }; - return runner.run(&path); + runner.run(&path) } } @@ -316,6 +316,7 @@ impl Default for ScriptsRepository { /// /// At this point, it only supports running a command in a chroot environment. In the future, it /// might implement support for other features, like progress reporting (like AutoYaST does). +#[derive(Default)] struct ScriptRunner { chroot: bool, } @@ -337,7 +338,7 @@ impl ScriptRunner { .args(["/mnt", &path.to_string_lossy()]) .output()? } else { - process::Command::new(&path).output()? + process::Command::new(path).output()? }; fs::write(path.with_extension("log"), output.stdout)?; @@ -348,12 +349,6 @@ impl ScriptRunner { } } -impl Default for ScriptRunner { - fn default() -> Self { - Self { chroot: false } - } -} - #[cfg(test)] mod test { use tempfile::TempDir; diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 5a901d29fb..26b63e48e3 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -191,9 +191,8 @@ impl<'a> SoftwareClient<'a> { resolvables: &[&str], optional: bool, ) -> Result<(), ServiceError> { - let names: Vec<_> = resolvables.iter().map(|r| r.as_ref()).collect(); self.proposal_proxy - .set_resolvables(id, r#type as u8, &names, optional) + .set_resolvables(id, r#type as u8, resolvables, optional) .await?; Ok(()) } diff --git a/rust/agama-lib/src/users/store.rs b/rust/agama-lib/src/users/store.rs index b8c2214604..67289d57d4 100644 --- a/rust/agama-lib/src/users/store.rs +++ b/rust/agama-lib/src/users/store.rs @@ -78,15 +78,13 @@ impl UsersStore { full_name: settings.full_name.clone().unwrap_or_default(), autologin: settings.autologin.unwrap_or_default(), password: settings.password.clone().unwrap_or_default(), - encrypted_password: settings.encrypted_password.clone().unwrap_or_default(), - ..Default::default() + encrypted_password: settings.encrypted_password.unwrap_or_default(), }; - self.users_client.set_first_user(&first_user).await?; - Ok(()) + self.users_client.set_first_user(&first_user).await } async fn store_root_user(&self, settings: &RootUserSettings) -> Result<(), ServiceError> { - let encrypted_password = settings.encrypted_password.clone().unwrap_or_default(); + let encrypted_password = settings.encrypted_password.unwrap_or_default(); if let Some(root_password) = &settings.password { self.users_client diff --git a/rust/agama-server/src/l10n.rs b/rust/agama-server/src/l10n.rs index 18f2eb7e83..fa78c2ea39 100644 --- a/rust/agama-server/src/l10n.rs +++ b/rust/agama-server/src/l10n.rs @@ -21,16 +21,10 @@ mod dbus; pub mod error; pub mod helpers; -mod keyboard; -pub mod l10n; -mod locale; -mod timezone; +mod model; pub mod web; pub use agama_lib::localization::model::LocaleConfig; pub use dbus::export_dbus_objects; pub use error::LocaleError; -pub use keyboard::Keymap; -pub use l10n::L10n; -pub use locale::LocaleEntry; -pub use timezone::TimezoneEntry; +pub use model::{Keymap, L10n, LocaleEntry, TimezoneEntry}; diff --git a/rust/agama-server/src/l10n/l10n.rs b/rust/agama-server/src/l10n/model.rs similarity index 97% rename from rust/agama-server/src/l10n/l10n.rs rename to rust/agama-server/src/l10n/model.rs index aaa3b83753..f6ad9b8120 100644 --- a/rust/agama-server/src/l10n/l10n.rs +++ b/rust/agama-server/src/l10n/model.rs @@ -28,10 +28,18 @@ use agama_locale_data::{KeymapId, LocaleId}; use regex::Regex; use subprocess::{Popen, PopenConfig, PopenError, Redirection}; -use super::keyboard::KeymapsDatabase; -use super::locale::LocalesDatabase; -use super::timezone::TimezonesDatabase; +pub mod keyboard; +pub mod locale; +pub mod timezone; + +pub use keyboard::Keymap; +pub use locale::LocaleEntry; +pub use timezone::TimezoneEntry; + use super::{helpers, LocaleError}; +use keyboard::KeymapsDatabase; +use locale::LocalesDatabase; +use timezone::TimezonesDatabase; pub struct L10n { pub timezone: String, diff --git a/rust/agama-server/src/l10n/keyboard.rs b/rust/agama-server/src/l10n/model/keyboard.rs similarity index 100% rename from rust/agama-server/src/l10n/keyboard.rs rename to rust/agama-server/src/l10n/model/keyboard.rs diff --git a/rust/agama-server/src/l10n/locale.rs b/rust/agama-server/src/l10n/model/locale.rs similarity index 100% rename from rust/agama-server/src/l10n/locale.rs rename to rust/agama-server/src/l10n/model/locale.rs diff --git a/rust/agama-server/src/l10n/timezone.rs b/rust/agama-server/src/l10n/model/timezone.rs similarity index 100% rename from rust/agama-server/src/l10n/timezone.rs rename to rust/agama-server/src/l10n/model/timezone.rs diff --git a/rust/agama-server/src/l10n/web.rs b/rust/agama-server/src/l10n/web.rs index 25d87df664..26bfe3e5d7 100644 --- a/rust/agama-server/src/l10n/web.rs +++ b/rust/agama-server/src/l10n/web.rs @@ -21,7 +21,8 @@ //! This module implements the web API for the localization module. use super::{ - error::LocaleError, keyboard::Keymap, locale::LocaleEntry, timezone::TimezoneEntry, L10n, + error::LocaleError, + model::{keyboard::Keymap, locale::LocaleEntry, timezone::TimezoneEntry, L10n}, }; use crate::{ error::Error, diff --git a/rust/agama-server/src/network.rs b/rust/agama-server/src/network.rs index fc2d9a6e20..3b0f5a89de 100644 --- a/rust/agama-server/src/network.rs +++ b/rust/agama-server/src/network.rs @@ -38,11 +38,11 @@ //! D-Bus interfaces depending on its type: //! //! * `org.opensuse.Agama1.Network.Connection` exposes common information across all connection -//! types. -//! * `org.opensuse.Agama1.Network.Connection.IPv4` includes IPv4 settings, like the configuration method -//! (DHCP, manual, etc.), IP addresses, name servers and so on. +//! types. +//! * `org.opensuse.Agama1.Network.Connection.IPv4` includes IPv4 settings, like the configuration +//! method (DHCP, manual, etc.), IP addresses, name servers and so on. //! * `org.opensuse.Agama1.Network.Connection.Wireless` exposes the configuration for wireless -//! connections. +//! connections. //! //! Analogous to the devices API, there is a special `/org/opensuse/Agama1/Network/connections` //! object that implements a few methods that are related to the collection of connections like @@ -55,7 +55,7 @@ //! them in mind: //! //! * The devices list does not reflect the changes in the system. For instance, it is not updated -//! when a device is connected to the system. +//! when a device is connected to the system. //! * Many configuration types are still missing (bridges, bonding, etc.). mod action; diff --git a/rust/agama-server/src/network/model.rs b/rust/agama-server/src/network/model.rs index 400a5ca23c..67795f5865 100644 --- a/rust/agama-server/src/network/model.rs +++ b/rust/agama-server/src/network/model.rs @@ -21,7 +21,7 @@ //! Representation of the network configuration //! //! * This module contains the types that represent the network concepts. They are supposed to be -//! agnostic from the real network service (e.g., NetworkManager). +//! agnostic from the real network service (e.g., NetworkManager). use crate::network::error::NetworkStateError; use agama_lib::network::settings::{ BondSettings, IEEE8021XSettings, NetworkConnection, WirelessSettings, diff --git a/rust/agama-server/src/network/nm/dbus.rs b/rust/agama-server/src/network/nm/dbus.rs index e2f9093044..e0674a06a1 100644 --- a/rust/agama-server/src/network/nm/dbus.rs +++ b/rust/agama-server/src/network/nm/dbus.rs @@ -518,7 +518,6 @@ fn bridge_config_from_dbus(conn: &OwnedNestedHash) -> Result Result, NmE mode, group: get_optional_property(tun, "group")?, owner: get_optional_property(tun, "owner")?, - ..Default::default() })) } @@ -1329,7 +1326,7 @@ mod test { metric: Some(100) }] ); - assert_eq!(connection.autoconnect, false); + assert!(!connection.autoconnect); Ok(()) } @@ -1574,7 +1571,6 @@ mod test { pairwise_algorithms: vec![PairwiseAlgorithm::Tkip, PairwiseAlgorithm::Ccmp], wpa_protocol_versions: vec![WPAProtocolVersion::Wpa], pmf: 1, - ..Default::default() }; let mut wireless = build_base_connection(); wireless.config = ConnectionConfig::Wireless(config); @@ -1933,7 +1929,7 @@ mod test { .unwrap() .downcast_ref() .unwrap(); - assert_eq!(autoconnect, false); + assert!(!autoconnect); let ethernet_connection = conn_dbus.get(ETHERNET_KEY).unwrap(); let mac_address: &str = ethernet_connection diff --git a/rust/agama-server/src/web/docs.rs b/rust/agama-server/src/web/docs.rs index 65eae4f79a..1592161228 100644 --- a/rust/agama-server/src/web/docs.rs +++ b/rust/agama-server/src/web/docs.rs @@ -36,6 +36,8 @@ mod users; pub use users::UsersApiDocBuilder; mod misc; pub use misc::MiscApiDocBuilder; +mod scripts; +pub use scripts::ScriptsApiDocBuilder; pub mod common; pub trait ApiDocBuilder { diff --git a/rust/agama-server/src/web/docs/common.rs b/rust/agama-server/src/web/docs/common.rs index 7deeb64166..0a5015cb87 100644 --- a/rust/agama-server/src/web/docs/common.rs +++ b/rust/agama-server/src/web/docs/common.rs @@ -30,13 +30,14 @@ use utoipa::openapi::{ }; /// Implements a builder for the issues API documentation. +#[derive(Default)] pub struct IssuesApiDocBuilder { paths: Vec<(String, PathItem)>, } impl IssuesApiDocBuilder { pub fn new() -> Self { - Self { paths: vec![] } + Default::default() } /// Adds a new issues API path. @@ -47,7 +48,7 @@ impl IssuesApiDocBuilder { pub fn add(self, path: &str, summary: &str, operation_id: &str) -> Self { let mut paths = self.paths; paths.push((path.to_string(), Self::issues_path(summary, operation_id))); - Self { paths, ..self } + Self { paths } } fn issues_path(summary: &'_ str, operation_id: &'_ str) -> PathItem { diff --git a/rust/agama-server/src/web/docs/scripts.rs b/rust/agama-server/src/web/docs/scripts.rs new file mode 100644 index 0000000000..54fbf3bece --- /dev/null +++ b/rust/agama-server/src/web/docs/scripts.rs @@ -0,0 +1,51 @@ +// Copyright (c) [2024] SUSE LLC +// +// All Rights Reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, contact SUSE LLC. +// +// To contact SUSE LLC about this file by physical or electronic mail, you may +// find current contact information at www.suse.com. + +use utoipa::openapi::{Components, ComponentsBuilder, Paths, PathsBuilder}; + +use super::ApiDocBuilder; + +pub struct ScriptsApiDocBuilder; + +impl ApiDocBuilder for ScriptsApiDocBuilder { + fn title(&self) -> String { + "Scripts HTTP API".to_string() + } + + fn paths(&self) -> Paths { + PathsBuilder::new() + .path_from::() + .path_from::() + .path_from::() + .path_from::() + .build() + } + + fn components(&self) -> Components { + ComponentsBuilder::new() + .schema_from::() + .schema_from::() + .schema_from::() + .schema_from::() + .schema_from::() + .schema_from::() + .build() + } +} diff --git a/rust/xtask/src/main.rs b/rust/xtask/src/main.rs index b7077130d1..9526a49409 100644 --- a/rust/xtask/src/main.rs +++ b/rust/xtask/src/main.rs @@ -6,8 +6,8 @@ mod tasks { use agama_cli::Cli; use agama_server::web::docs::{ ApiDocBuilder, L10nApiDocBuilder, ManagerApiDocBuilder, MiscApiDocBuilder, - NetworkApiDocBuilder, QuestionsApiDocBuilder, SoftwareApiDocBuilder, StorageApiDocBuilder, - UsersApiDocBuilder, + NetworkApiDocBuilder, QuestionsApiDocBuilder, ScriptsApiDocBuilder, SoftwareApiDocBuilder, + StorageApiDocBuilder, UsersApiDocBuilder, }; use clap::CommandFactory; use clap_complete::aot; @@ -62,12 +62,13 @@ mod tasks { write_openapi(L10nApiDocBuilder {}, out_dir.join("l10n.json"))?; write_openapi(ManagerApiDocBuilder {}, out_dir.join("manager.json"))?; + write_openapi(MiscApiDocBuilder {}, out_dir.join("misc.json"))?; write_openapi(NetworkApiDocBuilder {}, out_dir.join("network.json"))?; + write_openapi(QuestionsApiDocBuilder {}, out_dir.join("questions.json"))?; + write_openapi(ScriptsApiDocBuilder {}, out_dir.join("scripts.json"))?; write_openapi(SoftwareApiDocBuilder {}, out_dir.join("software.json"))?; write_openapi(StorageApiDocBuilder {}, out_dir.join("storage.json"))?; write_openapi(UsersApiDocBuilder {}, out_dir.join("users.json"))?; - write_openapi(QuestionsApiDocBuilder {}, out_dir.join("questions.json"))?; - write_openapi(MiscApiDocBuilder {}, out_dir.join("misc.json"))?; println!( "Generate the OpenAPI specification at {}.", out_dir.display()