From 2064e0c11ffb7284c2002b00dc62fd0b64ae39d1 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 4 Dec 2023 17:14:05 +0100 Subject: [PATCH 01/33] first WIP commit --- rust/agama-lib/src/install_settings.rs | 14 +++- rust/agama-lib/src/lib.rs | 1 + rust/agama-lib/src/product.rs | 10 +++ rust/agama-lib/src/product/client.rs | 85 +++++++++++++++++++++++++ rust/agama-lib/src/product/proxies.rs | 29 +++++++++ rust/agama-lib/src/product/settings.rs | 14 ++++ rust/agama-lib/src/product/store.rs | 42 ++++++++++++ rust/agama-lib/src/software.rs | 2 +- rust/agama-lib/src/software/client.rs | 70 ++++++++------------ rust/agama-lib/src/software/settings.rs | 5 +- rust/agama-lib/src/software/store.rs | 14 ++-- rust/agama-lib/src/store.rs | 4 +- 12 files changed, 234 insertions(+), 56 deletions(-) create mode 100644 rust/agama-lib/src/product.rs create mode 100644 rust/agama-lib/src/product/client.rs create mode 100644 rust/agama-lib/src/product/proxies.rs create mode 100644 rust/agama-lib/src/product/settings.rs create mode 100644 rust/agama-lib/src/product/store.rs diff --git a/rust/agama-lib/src/install_settings.rs b/rust/agama-lib/src/install_settings.rs index 1584385f3d..724d8129e8 100644 --- a/rust/agama-lib/src/install_settings.rs +++ b/rust/agama-lib/src/install_settings.rs @@ -3,7 +3,7 @@ //! This module implements the mechanisms to load and store the installation settings. use crate::{ network::NetworkSettings, software::SoftwareSettings, storage::StorageSettings, - users::UserSettings, + users::UserSettings, product::ProductSettings }; use agama_settings::Settings; use serde::{Deserialize, Serialize}; @@ -24,15 +24,18 @@ pub enum Scope { Storage, /// Network settings Network, + /// Product settings + Product, } impl Scope { /// Returns known scopes /// // TODO: we can rely on strum so we do not forget to add them - pub fn all() -> [Scope; 4] { + pub fn all() -> [Scope; 5] { [ Scope::Network, + Scope::Product, Scope::Software, Scope::Storage, Scope::Users, @@ -49,6 +52,7 @@ impl FromStr for Scope { "software" => Ok(Self::Software), "storage" => Ok(Self::Storage), "network" => Ok(Self::Network), + "product" => Ok(Self::Product), _ => Err("Unknown section"), } } @@ -69,6 +73,9 @@ pub struct InstallSettings { pub software: Option, #[serde(default)] #[settings(nested)] + pub product: Option, + #[serde(default)] + #[settings(nested)] pub storage: Option, #[serde(default)] #[settings(nested)] @@ -92,6 +99,9 @@ impl InstallSettings { if self.network.is_some() { scopes.push(Scope::Network); } + if self.product.is_some() { + scopes.push(Scope::Product); + } scopes } } diff --git a/rust/agama-lib/src/lib.rs b/rust/agama-lib/src/lib.rs index a3c055b55a..2440915df0 100644 --- a/rust/agama-lib/src/lib.rs +++ b/rust/agama-lib/src/lib.rs @@ -28,6 +28,7 @@ pub mod install_settings; pub mod manager; pub mod network; pub mod profile; +pub mod product; pub mod software; pub mod storage; pub mod users; diff --git a/rust/agama-lib/src/product.rs b/rust/agama-lib/src/product.rs new file mode 100644 index 0000000000..a7054785f1 --- /dev/null +++ b/rust/agama-lib/src/product.rs @@ -0,0 +1,10 @@ +//! Implements support for handling the users settings + +mod client; +mod proxies; +mod settings; +mod store; + +pub use client::ProductClient; +pub use settings::ProductSettings; +pub use store::ProductStore; diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs new file mode 100644 index 0000000000..d8aff9f13f --- /dev/null +++ b/rust/agama-lib/src/product/client.rs @@ -0,0 +1,85 @@ +use crate::software::proxies::SoftwareProductProxy; +use crate::error::ServiceError; +use serde::Serialize; +use zbus::Connection; + +use super::proxies::RegistrationProxy; + +/// Represents a software product +#[derive(Debug, Serialize)] +pub struct Product { + /// Product ID (eg., "ALP", "Tumbleweed", etc.) + pub id: String, + /// Product name (e.g., "openSUSE Tumbleweed") + pub name: String, + /// Product description + pub description: String, +} + +/// D-Bus client for the software service +pub struct ProductClient<'a> { + product_proxy: SoftwareProductProxy<'a>, + registration_proxy: RegistrationProxy<'a> +} + +impl<'a> ProductClient<'a> { + pub async fn new(connection: Connection) -> Result, ServiceError> { + Ok(Self { + product_proxy: SoftwareProductProxy::new(&connection).await?, + registration_proxy: RegistrationProxy::new(&connection).await? + }) + } + + /// Returns the available products + pub async fn products(&self) -> Result, ServiceError> { + let products: Vec = self + .product_proxy + .available_products() + .await? + .into_iter() + .map(|(id, name, data)| { + let description = match data.get("description") { + Some(value) => value.try_into().unwrap(), + None => "", + }; + Product { + id, + name, + description: description.to_string(), + } + }) + .collect(); + Ok(products) + } + + /// Returns the selected product to install + pub async fn product(&self) -> Result { + Ok(self.product_proxy.selected_product().await?) + } + + /// Selects the product to install + pub async fn select_product(&self, product_id: &str) -> Result<(), ServiceError> { + let result = self.product_proxy.select_product(product_id).await?; + + match result { + (0, _) => Ok(()), + (3, description) => { + let products = self.products().await?; + let ids: Vec = products.into_iter().map(|p| p.id).collect(); + let error = format!("{0}. Available products: '{1:?}'", description, ids); + Err(ServiceError::UnsuccessfulAction(error)) + } + (_, description) => Err(ServiceError::UnsuccessfulAction(description)), + } + } + + /// registration code used to register product + pub async fn registration_code(&self) -> Result{ + Ok(self.registration_proxy.reg_code().await?) + } + + /// email used to register product + pub async fn email(&self) -> Result{ + Ok(self.registration_proxy.email().await?) + } +} diff --git a/rust/agama-lib/src/product/proxies.rs b/rust/agama-lib/src/product/proxies.rs new file mode 100644 index 0000000000..064a212c3c --- /dev/null +++ b/rust/agama-lib/src/product/proxies.rs @@ -0,0 +1,29 @@ +//! # DBus interface proxy for: `org.opensuse.Agama1.Registration` +//! +//! This code was generated by `zbus-xmlgen` `3.1.1` from DBus introspection data. +use zbus::dbus_proxy; + +#[dbus_proxy(interface = "org.opensuse.Agama1.Registration", assume_defaults = true)] +trait Registration { + /// Deregister method + fn deregister(&self) -> zbus::Result<(u32, String)>; + + /// Register method + fn register( + &self, + reg_code: &str, + options: std::collections::HashMap<&str, zbus::zvariant::Value<'_>>, + ) -> zbus::Result<(u32, String)>; + + /// Email property + #[dbus_proxy(property)] + fn email(&self) -> zbus::Result; + + /// RegCode property + #[dbus_proxy(property)] + fn reg_code(&self) -> zbus::Result; + + /// Requirement property + #[dbus_proxy(property)] + fn requirement(&self) -> zbus::Result; +} diff --git a/rust/agama-lib/src/product/settings.rs b/rust/agama-lib/src/product/settings.rs new file mode 100644 index 0000000000..e474070c0f --- /dev/null +++ b/rust/agama-lib/src/product/settings.rs @@ -0,0 +1,14 @@ +//! Representation of the software settings + +use agama_settings::Settings; +use serde::{Deserialize, Serialize}; + +/// Software settings for installation +#[derive(Debug, Default, Settings, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ProductSettings { + /// ID of the product to install (e.g., "ALP", "Tumbleweed", etc.) + pub product: Option, + pub registration_code: Option, + pub email: Option +} diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs new file mode 100644 index 0000000000..1322842288 --- /dev/null +++ b/rust/agama-lib/src/product/store.rs @@ -0,0 +1,42 @@ +//! Implements the store for the storage settings. + +use super::{ProductClient, ProductSettings}; +use crate::error::ServiceError; +use crate::manager::ManagerClient; +use zbus::Connection; + +/// Loads and stores the software settings from/to the D-Bus service. +pub struct ProductStore<'a> { + product_client: ProductClient<'a>, + manager_client: ManagerClient<'a>, +} + +impl<'a> ProductStore<'a> { + pub async fn new(connection: Connection) -> Result, ServiceError> { + Ok(Self { + product_client: ProductClient::new(connection.clone()).await?, + manager_client: ManagerClient::new(connection).await?, + }) + } + + pub async fn load(&self) -> Result { + let product = self.product_client.product().await?; + let registration_code = self.product_client.registration_code().await?; + let email = self.product_client.email().await?; + + Ok(ProductSettings { + product: Some(product), + registration_code: Some(registration_code), + email: Some(email) + }) + } + + pub async fn store(&self, settings: &ProductSettings) -> Result<(), ServiceError> { + if let Some(product) = &settings.product { + self.product_client.select_product(product).await?; + self.manager_client.probe().await?; + } + + Ok(()) + } +} diff --git a/rust/agama-lib/src/software.rs b/rust/agama-lib/src/software.rs index b494e4f26c..53f2d6bf51 100644 --- a/rust/agama-lib/src/software.rs +++ b/rust/agama-lib/src/software.rs @@ -1,7 +1,7 @@ //! Implements support for handling the software settings mod client; -mod proxies; +pub mod proxies; mod settings; mod store; diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 2d6ae30c39..33954ce69a 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -1,71 +1,55 @@ -use super::proxies::SoftwareProductProxy; +use super::proxies::Software1Proxy; use crate::error::ServiceError; use serde::Serialize; use zbus::Connection; /// Represents a software product #[derive(Debug, Serialize)] -pub struct Product { - /// Product ID (eg., "ALP", "Tumbleweed", etc.) +pub struct Pattern { + /// Pattern ID (eg., "aaa_base", "gnome") pub id: String, - /// Product name (e.g., "openSUSE Tumbleweed") - pub name: String, - /// Product description + /// Pattern category (e.g., "Production") + pub category: String, + /// Pattern icon path locally on system + pub icon: String, + /// Pattern description pub description: String, + /// Pattern summary + pub summary: String, + /// Pattern order + pub order: String } /// D-Bus client for the software service pub struct SoftwareClient<'a> { - product_proxy: SoftwareProductProxy<'a>, + software_proxy: Software1Proxy<'a>, } impl<'a> SoftwareClient<'a> { pub async fn new(connection: Connection) -> Result, ServiceError> { Ok(Self { - product_proxy: SoftwareProductProxy::new(&connection).await?, + software_proxy: Software1Proxy::new(&connection).await?, }) } - /// Returns the available products - pub async fn products(&self) -> Result, ServiceError> { - let products: Vec = self - .product_proxy - .available_products() + /// Returns the available patterns + pub async fn patterns(&self, filtered: bool) -> Result, ServiceError> { + let patterns: Vec = self + .software_proxy + .list_patterns(filtered) .await? .into_iter() - .map(|(id, name, data)| { - let description = match data.get("description") { - Some(value) => value.try_into().unwrap(), - None => "", - }; - Product { + .map(|(id, (category, description, icon, summary, order))| { + Pattern { id, - name, - description: description.to_string(), + category, + icon, + description, + summary, + order } }) .collect(); - Ok(products) - } - - /// Returns the selected product to install - pub async fn product(&self) -> Result { - Ok(self.product_proxy.selected_product().await?) - } - - /// Selects the product to install - pub async fn select_product(&self, product_id: &str) -> Result<(), ServiceError> { - let result = self.product_proxy.select_product(product_id).await?; - - match result { - (0, _) => Ok(()), - (3, description) => { - let products = self.products().await?; - let ids: Vec = products.into_iter().map(|p| p.id).collect(); - let error = format!("{0}. Available products: '{1:?}'", description, ids); - Err(ServiceError::UnsuccessfulAction(error)) - } - (_, description) => Err(ServiceError::UnsuccessfulAction(description)), - } + Ok(patterns) } } diff --git a/rust/agama-lib/src/software/settings.rs b/rust/agama-lib/src/software/settings.rs index 9458b964d3..5412146938 100644 --- a/rust/agama-lib/src/software/settings.rs +++ b/rust/agama-lib/src/software/settings.rs @@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Settings, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SoftwareSettings { - /// ID of the product to install (e.g., "ALP", "Tumbleweed", etc.) - pub product: Option, + /// List of patterns to install. If not specified use default. + #[settings(collection)] + pub patterns: Vec, } diff --git a/rust/agama-lib/src/software/store.rs b/rust/agama-lib/src/software/store.rs index 9a8a5fb365..423cd508ef 100644 --- a/rust/agama-lib/src/software/store.rs +++ b/rust/agama-lib/src/software/store.rs @@ -20,18 +20,18 @@ impl<'a> SoftwareStore<'a> { } pub async fn load(&self) -> Result { - let product = self.software_client.product().await?; - + // TODO: real selected patterns Ok(SoftwareSettings { - product: Some(product), + patterns: vec![], }) } pub async fn store(&self, settings: &SoftwareSettings) -> Result<(), ServiceError> { - if let Some(product) = &settings.product { - self.software_client.select_product(product).await?; - self.manager_client.probe().await?; - } + // TODO: handle selected patterns + //if let Some(product) = &settings.product { + // self.software_client.select_product(product).await?; + // self.manager_client.probe().await?; + //} Ok(()) } diff --git a/rust/agama-lib/src/store.rs b/rust/agama-lib/src/store.rs index ae3ee8f082..817a5520f9 100644 --- a/rust/agama-lib/src/store.rs +++ b/rust/agama-lib/src/store.rs @@ -3,7 +3,7 @@ use crate::error::ServiceError; use crate::install_settings::{InstallSettings, Scope}; use crate::{ - network::NetworkStore, software::SoftwareStore, storage::StorageStore, users::UsersStore, + network::NetworkStore, software::SoftwareStore, storage::StorageStore, users::UsersStore, product::ProductStore }; use zbus::Connection; @@ -16,6 +16,7 @@ use zbus::Connection; pub struct Store<'a> { users: UsersStore<'a>, network: NetworkStore<'a>, + product: ProductStore<'a>, software: SoftwareStore<'a>, storage: StorageStore<'a>, } @@ -25,6 +26,7 @@ impl<'a> Store<'a> { Ok(Self { users: UsersStore::new(connection.clone()).await?, network: NetworkStore::new(connection.clone()).await?, + product: ProductStore::new(connection.clone()).await?, software: SoftwareStore::new(connection.clone()).await?, storage: StorageStore::new(connection).await?, }) From eb93fc7a9f2375f458208d8b0e53954ad3897eb9 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 4 Dec 2023 21:11:52 +0100 Subject: [PATCH 02/33] more code and patch from @imobachgs --- rust/agama-lib/src/software/store.rs | 3 --- rust/agama-lib/src/store.rs | 9 +++++++++ rust/agama-settings/src/settings.rs | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/software/store.rs b/rust/agama-lib/src/software/store.rs index 423cd508ef..d82f283bce 100644 --- a/rust/agama-lib/src/software/store.rs +++ b/rust/agama-lib/src/software/store.rs @@ -2,20 +2,17 @@ use super::{SoftwareClient, SoftwareSettings}; use crate::error::ServiceError; -use crate::manager::ManagerClient; use zbus::Connection; /// Loads and stores the software settings from/to the D-Bus service. pub struct SoftwareStore<'a> { software_client: SoftwareClient<'a>, - manager_client: ManagerClient<'a>, } impl<'a> SoftwareStore<'a> { pub async fn new(connection: Connection) -> Result, ServiceError> { Ok(Self { software_client: SoftwareClient::new(connection.clone()).await?, - manager_client: ManagerClient::new(connection).await?, }) } diff --git a/rust/agama-lib/src/store.rs b/rust/agama-lib/src/store.rs index 817a5520f9..b6d114a130 100644 --- a/rust/agama-lib/src/store.rs +++ b/rust/agama-lib/src/store.rs @@ -55,6 +55,10 @@ impl<'a> Store<'a> { settings.user = Some(self.users.load().await?); } + if scopes.contains(&Scope::Product) { + settings.product = Some(self.product.load().await?); + } + // TODO: use try_join here Ok(settings) } @@ -64,6 +68,11 @@ impl<'a> Store<'a> { if let Some(network) = &settings.network { self.network.store(network).await?; } + // order is important here as network can be critical for connection + // to registration server and selecting product is important for rest + if let Some(product) = &settings.product { + self.product.store(product).await?; + } if let Some(software) = &settings.software { self.software.store(software).await?; } diff --git a/rust/agama-settings/src/settings.rs b/rust/agama-settings/src/settings.rs index 0692d9ec78..240a6cd854 100644 --- a/rust/agama-settings/src/settings.rs +++ b/rust/agama-settings/src/settings.rs @@ -80,6 +80,23 @@ impl From> for SettingObject { } } +impl From for SettingObject { + fn from(value: String) -> SettingObject { + SettingObject(HashMap::from([("value".to_string(), SettingValue(value))])) + } +} + +impl TryFrom for String { + type Error = ConversionError; + + fn try_from(value: SettingObject) -> Result { + if let Some(v) = value.get("value") { + return Ok(v.to_string()); + } + Err(ConversionError::MissingKey("value".to_string())) + } +} + impl TryFrom for bool { type Error = ConversionError; From a37c783b0cce96b8074e52b61bfa77235172ce58 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Tue, 5 Dec 2023 12:25:03 +0100 Subject: [PATCH 03/33] more code and adapt schema --- rust/agama-lib/share/profile.schema.json | 20 +++++++++++++++++++- rust/agama-lib/src/product/client.rs | 9 +++++++++ rust/agama-lib/src/product/store.rs | 9 +++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) diff --git a/rust/agama-lib/share/profile.schema.json b/rust/agama-lib/share/profile.schema.json index 2d9cb33b0a..c729368cb6 100644 --- a/rust/agama-lib/share/profile.schema.json +++ b/rust/agama-lib/share/profile.schema.json @@ -10,9 +10,27 @@ "description": "Software settings (e.g., product to install)", "type": "object", "properties": { - "product": { + "patterns": { + "description": "List of patterns to install", + "type": "array" + } + } + }, + "product": { + "description": "Software settings (e.g., product to install)", + "type": "object", + "properties": { + "id": { "description": "Product identifier", "type": "string" + }, + "registrationCode": { + "description": "Product registration code", + "type": "string" + }, + "registrationEmail": { + "description": "Product registration email", + "type": "string" } } }, diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index d8aff9f13f..54f9d3e79e 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::software::proxies::SoftwareProductProxy; use crate::error::ServiceError; use serde::Serialize; @@ -82,4 +84,11 @@ impl<'a> ProductClient<'a> { pub async fn email(&self) -> Result{ Ok(self.registration_proxy.email().await?) } + + /// register product + pub async fn register(&self, code :&str, _email: &str) -> Result<(), ServiceError> { + // TODO: handle email + self.registration_proxy.register(code, HashMap::new()).await?; + Ok(()) + } } diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 1322842288..ead5a33246 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -32,8 +32,17 @@ impl<'a> ProductStore<'a> { } pub async fn store(&self, settings: &ProductSettings) -> Result<(), ServiceError> { + let mut probe = false; if let Some(product) = &settings.product { self.product_client.select_product(product).await?; + probe = true; + } + if let Some(reg_code) = &settings.registration_code { + let email = settings.email.clone().unwrap_or_default(); + self.product_client.register(reg_code, &email).await?; + } + + if probe { self.manager_client.probe().await?; } From 81e58134bd94b0c4d324d5beb05eaa90fdb705fb Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 6 Dec 2023 12:10:22 +0100 Subject: [PATCH 04/33] final push for testing --- rust/agama-lib/src/product/store.rs | 1 + rust/agama-lib/src/software/client.rs | 25 +++++++++++++++++++++++++ rust/agama-lib/src/software/store.rs | 10 +++------- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index ead5a33246..f3f32cf9cc 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -40,6 +40,7 @@ impl<'a> ProductStore<'a> { if let Some(reg_code) = &settings.registration_code { let email = settings.email.clone().unwrap_or_default(); self.product_client.register(reg_code, &email).await?; + probe = true; } if probe { diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 33954ce69a..e254972d12 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -52,4 +52,29 @@ impl<'a> SoftwareClient<'a> { .collect(); Ok(patterns) } + + /// Returns the selected patterns by user + pub async fn user_selected_patterns(&self) -> Result, ServiceError> { + const USER_SELECTED: u8 = 0; + let patterns: Vec = self + .software_proxy + .selected_patterns() + .await? + .into_iter() + .filter(|(_id, reason)| { + *reason == USER_SELECTED + }) + .map(|(id, _reason)| { + id + }) + .collect(); + Ok(patterns) + } + + /// Selects patterns by user + pub async fn select_patterns(&self, patterns: &Vec) -> Result<(), ServiceError> { + let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); + self.software_proxy.set_user_patterns(patterns.as_slice()).await?; + Ok(()) + } } diff --git a/rust/agama-lib/src/software/store.rs b/rust/agama-lib/src/software/store.rs index d82f283bce..367a05c26c 100644 --- a/rust/agama-lib/src/software/store.rs +++ b/rust/agama-lib/src/software/store.rs @@ -17,18 +17,14 @@ impl<'a> SoftwareStore<'a> { } pub async fn load(&self) -> Result { - // TODO: real selected patterns + let patterns = self.software_client.user_selected_patterns().await?; Ok(SoftwareSettings { - patterns: vec![], + patterns, }) } pub async fn store(&self, settings: &SoftwareSettings) -> Result<(), ServiceError> { - // TODO: handle selected patterns - //if let Some(product) = &settings.product { - // self.software_client.select_product(product).await?; - // self.manager_client.probe().await?; - //} + self.software_client.select_patterns(&settings.patterns).await?; Ok(()) } From 7c170a87e220f78a13f50e6caf0d44bd0af84cbb Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 6 Dec 2023 14:13:44 +0100 Subject: [PATCH 05/33] fix dbus path and update example profile for TW --- rust/agama-lib/share/examples/profile.json | 7 ++++++- rust/agama-lib/src/product/proxies.rs | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rust/agama-lib/share/examples/profile.json b/rust/agama-lib/share/examples/profile.json index 0aae970862..b55d82423a 100644 --- a/rust/agama-lib/share/examples/profile.json +++ b/rust/agama-lib/share/examples/profile.json @@ -4,7 +4,12 @@ "language": "en_US" }, "software": { - "product": "ALP-Dolomite" + "patterns": [ + "gnome" + ] + }, + "product": { + "id": "Tumbleweed" }, "storage": { "bootDevice": "/dev/dm-1" diff --git a/rust/agama-lib/src/product/proxies.rs b/rust/agama-lib/src/product/proxies.rs index 064a212c3c..1fd258f2fa 100644 --- a/rust/agama-lib/src/product/proxies.rs +++ b/rust/agama-lib/src/product/proxies.rs @@ -3,7 +3,11 @@ //! This code was generated by `zbus-xmlgen` `3.1.1` from DBus introspection data. use zbus::dbus_proxy; -#[dbus_proxy(interface = "org.opensuse.Agama1.Registration", assume_defaults = true)] +#[dbus_proxy( + interface = "org.opensuse.Agama1.Registration", + default_service = "org.opensuse.Agama.Software1", + default_path = "/org/opensuse/Agama/Software1/Product" +)] trait Registration { /// Deregister method fn deregister(&self) -> zbus::Result<(u32, String)>; From 8b59f230c1d37a208cbffcde3a41faeccfe3d879 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 6 Dec 2023 21:17:20 +0100 Subject: [PATCH 06/33] fix product key reading and fix ruby dbus crash --- rust/agama-lib/src/product/settings.rs | 2 +- rust/agama-lib/src/product/store.rs | 4 ++-- service/lib/agama/software/manager.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/agama-lib/src/product/settings.rs b/rust/agama-lib/src/product/settings.rs index e474070c0f..b3ab4e882b 100644 --- a/rust/agama-lib/src/product/settings.rs +++ b/rust/agama-lib/src/product/settings.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; #[serde(rename_all = "camelCase")] pub struct ProductSettings { /// ID of the product to install (e.g., "ALP", "Tumbleweed", etc.) - pub product: Option, + pub id: Option, pub registration_code: Option, pub email: Option } diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index f3f32cf9cc..8014b64ad3 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -25,7 +25,7 @@ impl<'a> ProductStore<'a> { let email = self.product_client.email().await?; Ok(ProductSettings { - product: Some(product), + id: Some(product), registration_code: Some(registration_code), email: Some(email) }) @@ -33,7 +33,7 @@ impl<'a> ProductStore<'a> { pub async fn store(&self, settings: &ProductSettings) -> Result<(), ServiceError> { let mut probe = false; - if let Some(product) = &settings.product { + if let Some(product) = &settings.id { self.product_client.select_product(product).await?; probe = true; } diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index be47087609..e300844709 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -244,7 +244,7 @@ def user_patterns=(ids) user_patterns.each { |p| Yast::Pkg.ResolvableNeutral(p, :pattern, force = false) } Yast::PackagesProposal.SetResolvables(PROPOSAL_ID, :pattern, ids) ids.each { |p| Yast::Pkg.ResolvableInstall(p, :pattern) } - logger.info "Setting patterns to #{res.inspect}" + logger.info "Setting patterns to #{ids.inspect}" res = Yast::Pkg.PkgSolve(unused = true) logger.info "Solver run #{res.inspect}" From e3b6946ab766914f3d9146227ba22d0cda51c95d Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 10:52:17 +0100 Subject: [PATCH 07/33] add example for registration and also fix bug that single product media failed if product is specified --- .../share/examples/profile_Dolomite.json | 43 +++++++++++++++++++ .../{profile.json => profile_tw.json} | 0 rust/agama-lib/src/product/store.rs | 8 +++- 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 rust/agama-lib/share/examples/profile_Dolomite.json rename rust/agama-lib/share/examples/{profile.json => profile_tw.json} (100%) diff --git a/rust/agama-lib/share/examples/profile_Dolomite.json b/rust/agama-lib/share/examples/profile_Dolomite.json new file mode 100644 index 0000000000..16ba127267 --- /dev/null +++ b/rust/agama-lib/share/examples/profile_Dolomite.json @@ -0,0 +1,43 @@ +{ + "localization": { + "keyboard": "en_US", + "language": "en_US" + }, + "product": { + "id": "ALP-Dolomite", + "registrationCode": "FILL IT UP", + "registrationEmail": "jreidinger@suse.com" + }, + "storage": { + "bootDevice": "/dev/dm-1" + }, + "user": { + "fullName": "Jane Doe", + "password": "123456", + "userName": "jane.doe" + }, + "root": { + "password": "nots3cr3t", + "sshKey": "..." + }, + "network": { + "connections": [ + { + "id": "Ethernet network device 1", + "method4": "manual", + "method6": "manual", + "interface": "eth0", + "addresses": [ + "192.168.122.100/24", + "::ffff:c0a8:7ac7/64" + ], + "gateway4": "192.168.122.1", + "gateway6": "::ffff:c0a8:7a01", + "nameservers": [ + "192.168.122.1", + "2001:4860:4860::8888" + ] + } + ] + } +} diff --git a/rust/agama-lib/share/examples/profile.json b/rust/agama-lib/share/examples/profile_tw.json similarity index 100% rename from rust/agama-lib/share/examples/profile.json rename to rust/agama-lib/share/examples/profile_tw.json diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 8014b64ad3..3b58dac5f1 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -34,8 +34,12 @@ impl<'a> ProductStore<'a> { pub async fn store(&self, settings: &ProductSettings) -> Result<(), ServiceError> { let mut probe = false; if let Some(product) = &settings.id { - self.product_client.select_product(product).await?; - probe = true; + let existing_product = self.product_client.product().await?; + if *product != existing_product { + // avoid selecting same product and unnecessary probe + self.product_client.select_product(product).await?; + probe = true; + } } if let Some(reg_code) = &settings.registration_code { let email = settings.email.clone().unwrap_or_default(); From a9f6e255eb17aa58442b748619c96c7efd8f6d0b Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 11:53:58 +0100 Subject: [PATCH 08/33] format rust --- rust/agama-lib/src/install_settings.rs | 4 ++-- rust/agama-lib/src/lib.rs | 2 +- rust/agama-lib/src/product/client.rs | 16 +++++++++------- rust/agama-lib/src/product/settings.rs | 2 +- rust/agama-lib/src/product/store.rs | 2 +- rust/agama-lib/src/software/client.rs | 24 +++++++++++------------- rust/agama-lib/src/software/store.rs | 8 ++++---- rust/agama-lib/src/store.rs | 3 ++- 8 files changed, 31 insertions(+), 30 deletions(-) diff --git a/rust/agama-lib/src/install_settings.rs b/rust/agama-lib/src/install_settings.rs index 724d8129e8..b1b9a398ab 100644 --- a/rust/agama-lib/src/install_settings.rs +++ b/rust/agama-lib/src/install_settings.rs @@ -2,8 +2,8 @@ //! //! This module implements the mechanisms to load and store the installation settings. use crate::{ - network::NetworkSettings, software::SoftwareSettings, storage::StorageSettings, - users::UserSettings, product::ProductSettings + network::NetworkSettings, product::ProductSettings, software::SoftwareSettings, + storage::StorageSettings, users::UserSettings, }; use agama_settings::Settings; use serde::{Deserialize, Serialize}; diff --git a/rust/agama-lib/src/lib.rs b/rust/agama-lib/src/lib.rs index 2440915df0..e71c9ff6e4 100644 --- a/rust/agama-lib/src/lib.rs +++ b/rust/agama-lib/src/lib.rs @@ -27,8 +27,8 @@ pub mod error; pub mod install_settings; pub mod manager; pub mod network; -pub mod profile; pub mod product; +pub mod profile; pub mod software; pub mod storage; pub mod users; diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index 54f9d3e79e..8d0e090ccb 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; -use crate::software::proxies::SoftwareProductProxy; use crate::error::ServiceError; +use crate::software::proxies::SoftwareProductProxy; use serde::Serialize; use zbus::Connection; @@ -21,14 +21,14 @@ pub struct Product { /// D-Bus client for the software service pub struct ProductClient<'a> { product_proxy: SoftwareProductProxy<'a>, - registration_proxy: RegistrationProxy<'a> + registration_proxy: RegistrationProxy<'a>, } impl<'a> ProductClient<'a> { pub async fn new(connection: Connection) -> Result, ServiceError> { Ok(Self { product_proxy: SoftwareProductProxy::new(&connection).await?, - registration_proxy: RegistrationProxy::new(&connection).await? + registration_proxy: RegistrationProxy::new(&connection).await?, }) } @@ -76,19 +76,21 @@ impl<'a> ProductClient<'a> { } /// registration code used to register product - pub async fn registration_code(&self) -> Result{ + pub async fn registration_code(&self) -> Result { Ok(self.registration_proxy.reg_code().await?) } /// email used to register product - pub async fn email(&self) -> Result{ + pub async fn email(&self) -> Result { Ok(self.registration_proxy.email().await?) } /// register product - pub async fn register(&self, code :&str, _email: &str) -> Result<(), ServiceError> { + pub async fn register(&self, code: &str, _email: &str) -> Result<(), ServiceError> { // TODO: handle email - self.registration_proxy.register(code, HashMap::new()).await?; + self.registration_proxy + .register(code, HashMap::new()) + .await?; Ok(()) } } diff --git a/rust/agama-lib/src/product/settings.rs b/rust/agama-lib/src/product/settings.rs index b3ab4e882b..dff0c01c8e 100644 --- a/rust/agama-lib/src/product/settings.rs +++ b/rust/agama-lib/src/product/settings.rs @@ -10,5 +10,5 @@ pub struct ProductSettings { /// ID of the product to install (e.g., "ALP", "Tumbleweed", etc.) pub id: Option, pub registration_code: Option, - pub email: Option + pub email: Option, } diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 3b58dac5f1..f2559e1d34 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -27,7 +27,7 @@ impl<'a> ProductStore<'a> { Ok(ProductSettings { id: Some(product), registration_code: Some(registration_code), - email: Some(email) + email: Some(email), }) } diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index e254972d12..60d3cb571e 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -17,7 +17,7 @@ pub struct Pattern { /// Pattern summary pub summary: String, /// Pattern order - pub order: String + pub order: String, } /// D-Bus client for the software service @@ -39,16 +39,16 @@ impl<'a> SoftwareClient<'a> { .list_patterns(filtered) .await? .into_iter() - .map(|(id, (category, description, icon, summary, order))| { - Pattern { + .map( + |(id, (category, description, icon, summary, order))| Pattern { id, category, icon, description, summary, - order - } - }) + order, + }, + ) .collect(); Ok(patterns) } @@ -61,12 +61,8 @@ impl<'a> SoftwareClient<'a> { .selected_patterns() .await? .into_iter() - .filter(|(_id, reason)| { - *reason == USER_SELECTED - }) - .map(|(id, _reason)| { - id - }) + .filter(|(_id, reason)| *reason == USER_SELECTED) + .map(|(id, _reason)| id) .collect(); Ok(patterns) } @@ -74,7 +70,9 @@ impl<'a> SoftwareClient<'a> { /// Selects patterns by user pub async fn select_patterns(&self, patterns: &Vec) -> Result<(), ServiceError> { let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); - self.software_proxy.set_user_patterns(patterns.as_slice()).await?; + self.software_proxy + .set_user_patterns(patterns.as_slice()) + .await?; Ok(()) } } diff --git a/rust/agama-lib/src/software/store.rs b/rust/agama-lib/src/software/store.rs index 367a05c26c..66b6f6b092 100644 --- a/rust/agama-lib/src/software/store.rs +++ b/rust/agama-lib/src/software/store.rs @@ -18,13 +18,13 @@ impl<'a> SoftwareStore<'a> { pub async fn load(&self) -> Result { let patterns = self.software_client.user_selected_patterns().await?; - Ok(SoftwareSettings { - patterns, - }) + Ok(SoftwareSettings { patterns }) } pub async fn store(&self, settings: &SoftwareSettings) -> Result<(), ServiceError> { - self.software_client.select_patterns(&settings.patterns).await?; + self.software_client + .select_patterns(&settings.patterns) + .await?; Ok(()) } diff --git a/rust/agama-lib/src/store.rs b/rust/agama-lib/src/store.rs index b6d114a130..1f0d4e5c15 100644 --- a/rust/agama-lib/src/store.rs +++ b/rust/agama-lib/src/store.rs @@ -3,7 +3,8 @@ use crate::error::ServiceError; use crate::install_settings::{InstallSettings, Scope}; use crate::{ - network::NetworkStore, software::SoftwareStore, storage::StorageStore, users::UsersStore, product::ProductStore + network::NetworkStore, product::ProductStore, software::SoftwareStore, storage::StorageStore, + users::UsersStore, }; use zbus::Connection; From 0a39902715b2b5bad32d93a80c4594bd8a587531 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 16:32:28 +0100 Subject: [PATCH 09/33] Apply clippy suggestions --- rust/agama-lib/src/network/client.rs | 2 +- rust/agama-lib/src/software/client.rs | 2 +- rust/agama-lib/src/storage/client.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/network/client.rs b/rust/agama-lib/src/network/client.rs index 485baee516..b1ddaaf46b 100644 --- a/rust/agama-lib/src/network/client.rs +++ b/rust/agama-lib/src/network/client.rs @@ -22,7 +22,7 @@ impl<'a> NetworkClient<'a> { pub async fn get_connection(&self, id: &str) -> Result { let path = self.connections_proxy.get_connection(id).await?; - Ok(self.connection_from(path.as_str()).await?) + self.connection_from(path.as_str()).await } /// Returns an array of network connections diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 60d3cb571e..f45e01dad9 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -68,7 +68,7 @@ impl<'a> SoftwareClient<'a> { } /// Selects patterns by user - pub async fn select_patterns(&self, patterns: &Vec) -> Result<(), ServiceError> { + pub async fn select_patterns(&self, patterns: &[String]) -> Result<(), ServiceError> { let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); self.software_proxy .set_user_patterns(patterns.as_slice()) diff --git a/rust/agama-lib/src/storage/client.rs b/rust/agama-lib/src/storage/client.rs index 7cdbb0e37e..06455992b8 100644 --- a/rust/agama-lib/src/storage/client.rs +++ b/rust/agama-lib/src/storage/client.rs @@ -52,7 +52,7 @@ impl<'a> StorageClient<'a> { .map(|path| self.storage_device(path)) .collect(); - return join_all(devices).await.into_iter().collect(); + join_all(devices).await.into_iter().collect() } /// Returns the storage device for the given D-Bus path From 73d42560783108b89d0fc98afc2c5d33eebd7239 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 16:34:58 +0100 Subject: [PATCH 10/33] more clippy suggestions --- rust/agama-dbus-server/src/locale/helpers.rs | 2 +- rust/agama-dbus-server/src/locale/locale.rs | 8 +++--- rust/agama-dbus-server/src/locale/timezone.rs | 8 +++--- rust/agama-dbus-server/src/main.rs | 2 +- rust/agama-dbus-server/src/network.rs | 2 +- rust/agama-dbus-server/src/network/nm/dbus.rs | 25 ++++++------------- rust/agama-dbus-server/src/questions.rs | 2 +- rust/agama-dbus-server/tests/common/mod.rs | 6 ++--- rust/agama-dbus-server/tests/network.rs | 6 ++--- 9 files changed, 26 insertions(+), 35 deletions(-) diff --git a/rust/agama-dbus-server/src/locale/helpers.rs b/rust/agama-dbus-server/src/locale/helpers.rs index d9e65b6de7..490203d5b1 100644 --- a/rust/agama-dbus-server/src/locale/helpers.rs +++ b/rust/agama-dbus-server/src/locale/helpers.rs @@ -23,7 +23,7 @@ pub fn init_locale() -> Result> { /// pub fn set_service_locale(locale: &LocaleCode) { // Let's force the encoding to be 'UTF-8'. - let locale = format!("{}.UTF-8", locale.to_string()); + let locale = format!("{}.UTF-8", locale); if setlocale(LocaleCategory::LcAll, locale).is_none() { log::warn!("Could not set the locale"); } diff --git a/rust/agama-dbus-server/src/locale/locale.rs b/rust/agama-dbus-server/src/locale/locale.rs index 88a6b4c95e..2bfba9aab7 100644 --- a/rust/agama-dbus-server/src/locale/locale.rs +++ b/rust/agama-dbus-server/src/locale/locale.rs @@ -45,7 +45,7 @@ impl LocalesDatabase { .lines() .filter_map(|line| TryInto::::try_into(line).ok()) .collect(); - self.locales = self.get_locales(&ui_language)?; + self.locales = self.get_locales(ui_language)?; Ok(()) } @@ -82,7 +82,7 @@ impl LocalesDatabase { let names = &language.names; let language_label = names - .name_for(&ui_language) + .name_for(ui_language) .or_else(|| names.name_for(DEFAULT_LANG)) .unwrap_or(language.id.to_string()); @@ -92,7 +92,7 @@ impl LocalesDatabase { let names = &territory.names; let territory_label = names - .name_for(&ui_language) + .name_for(ui_language) .or_else(|| names.name_for(DEFAULT_LANG)) .unwrap_or(territory.id.to_string()); @@ -121,7 +121,7 @@ mod tests { let found_locales = db.entries(); let spanish: LocaleCode = "es_ES".try_into().unwrap(); let found = found_locales - .into_iter() + .iter() .find(|l| l.code == spanish) .unwrap(); assert_eq!(&found.language, "Spanisch"); diff --git a/rust/agama-dbus-server/src/locale/timezone.rs b/rust/agama-dbus-server/src/locale/timezone.rs index 8b60197a45..f26917b6af 100644 --- a/rust/agama-dbus-server/src/locale/timezone.rs +++ b/rust/agama-dbus-server/src/locale/timezone.rs @@ -52,7 +52,7 @@ impl TimezonesDatabase { let ret = timezones .into_iter() .map(|tz| { - let parts = translate_parts(&tz, &ui_language, &tz_parts); + let parts = translate_parts(&tz, ui_language, &tz_parts); TimezoneEntry { code: tz, parts } }) .collect(); @@ -62,10 +62,10 @@ impl TimezonesDatabase { fn translate_parts(timezone: &str, ui_language: &str, tz_parts: &TimezoneIdParts) -> Vec { timezone - .split("/") + .split('/') .map(|part| { tz_parts - .localize_part(part, &ui_language) + .localize_part(part, ui_language) .unwrap_or(part.to_owned()) }) .collect() @@ -82,7 +82,7 @@ mod tests { let found_timezones = db.entries(); dbg!(&found_timezones); let found = found_timezones - .into_iter() + .iter() .find(|tz| tz.code == "Europe/Berlin") .unwrap(); assert_eq!(&found.code, "Europe/Berlin"); diff --git a/rust/agama-dbus-server/src/main.rs b/rust/agama-dbus-server/src/main.rs index 33c0c41db8..e8dd97d73a 100644 --- a/rust/agama-dbus-server/src/main.rs +++ b/rust/agama-dbus-server/src/main.rs @@ -4,7 +4,7 @@ use agama_lib::connection_to; use anyhow::Context; use log::{self, LevelFilter}; use std::future::pending; -use tokio; + const ADDRESS: &str = "unix:path=/run/agama/bus"; const SERVICE_NAME: &str = "org.opensuse.Agama1"; diff --git a/rust/agama-dbus-server/src/network.rs b/rust/agama-dbus-server/src/network.rs index edf2e82e7b..35158a10a8 100644 --- a/rust/agama-dbus-server/src/network.rs +++ b/rust/agama-dbus-server/src/network.rs @@ -60,5 +60,5 @@ pub async fn export_dbus_objects( let adapter = NetworkManagerAdapter::from_system() .await .expect("Could not connect to NetworkManager to read the configuration."); - NetworkService::start(&connection, adapter).await + NetworkService::start(connection, adapter).await } diff --git a/rust/agama-dbus-server/src/network/nm/dbus.rs b/rust/agama-dbus-server/src/network/nm/dbus.rs index d601291e9f..5eade2265a 100644 --- a/rust/agama-dbus-server/src/network/nm/dbus.rs +++ b/rust/agama-dbus-server/src/network/nm/dbus.rs @@ -106,7 +106,7 @@ fn cleanup_dbus_connection(conn: &mut NestedHash) { if let Some(connection) = conn.get_mut("connection") { if connection .get("interface-name") - .is_some_and(|v| is_empty_value(&v)) + .is_some_and(is_empty_value) { connection.remove("interface-name"); } @@ -238,26 +238,17 @@ fn wireless_config_to_dbus(conn: &WirelessConnection) -> NestedHash { /// * `match_config`: MatchConfig to convert. fn match_config_to_dbus(match_config: &MatchConfig) -> HashMap<&str, zvariant::Value> { let drivers: Value = match_config - .driver - .iter() - .cloned() - .collect::>() + .driver.to_vec() .into(); let kernels: Value = match_config - .kernel - .iter() - .cloned() - .collect::>() + .kernel.to_vec() .into(); - let paths: Value = match_config.path.iter().cloned().collect::>().into(); + let paths: Value = match_config.path.to_vec().into(); let interfaces: Value = match_config - .interface - .iter() - .cloned() - .collect::>() + .interface.to_vec() .into(); HashMap::from([ @@ -291,7 +282,7 @@ fn base_connection_from_dbus(conn: &OwnedNestedHash) -> Option { base_connection.match_config = match_config_from_dbus(match_config)?; } - base_connection.ip_config = ip_config_from_dbus(&conn)?; + base_connection.ip_config = ip_config_from_dbus(conn)?; Some(base_connection) } @@ -344,7 +335,7 @@ fn ip_config_from_dbus(conn: &OwnedNestedHash) -> Option { ip_config.method4 = NmMethod(method4.to_string()).try_into().ok()?; let address_data = ipv4.get("address-data")?; - let mut addresses = addresses_with_prefix_from_dbus(&address_data)?; + let mut addresses = addresses_with_prefix_from_dbus(address_data)?; ip_config.addresses.append(&mut addresses); @@ -368,7 +359,7 @@ fn ip_config_from_dbus(conn: &OwnedNestedHash) -> Option { ip_config.method6 = NmMethod(method6.to_string()).try_into().ok()?; let address_data = ipv6.get("address-data")?; - let mut addresses = addresses_with_prefix_from_dbus(&address_data)?; + let mut addresses = addresses_with_prefix_from_dbus(address_data)?; ip_config.addresses.append(&mut addresses); diff --git a/rust/agama-dbus-server/src/questions.rs b/rust/agama-dbus-server/src/questions.rs index 2f45d69442..fda860bf6d 100644 --- a/rust/agama-dbus-server/src/questions.rs +++ b/rust/agama-dbus-server/src/questions.rs @@ -334,7 +334,7 @@ pub async fn export_dbus_objects( const PATH: &str = "/org/opensuse/Agama1/Questions"; // When serving, request the service name _after_ exposing the main object - let questions = Questions::new(&connection); + let questions = Questions::new(connection); connection.object_server().at(PATH, questions).await?; connection.object_server().at(PATH, ObjectManager).await?; diff --git a/rust/agama-dbus-server/tests/common/mod.rs b/rust/agama-dbus-server/tests/common/mod.rs index 5c7cd9e6ba..47841518e8 100644 --- a/rust/agama-dbus-server/tests/common/mod.rs +++ b/rust/agama-dbus-server/tests/common/mod.rs @@ -5,7 +5,7 @@ use std::{ process::{Child, Command}, time::Duration, }; -use tokio; + use tokio_stream::StreamExt; use uuid::Uuid; use zbus::{MatchRule, MessageStream, MessageType}; @@ -101,7 +101,7 @@ impl NameOwnerChangedStream { .sender("org.freedesktop.DBus")? .member("NameOwnerChanged")? .build(); - let stream = MessageStream::for_match_rule(rule, &connection, None).await?; + let stream = MessageStream::for_match_rule(rule, connection, None).await?; Ok(Self(stream)) } @@ -137,7 +137,7 @@ where if retry > RETRIES { return Err(error); } - retry = retry + 1; + retry += 1; let wait_time = Duration::from_millis(INTERVAL); tokio::time::sleep(wait_time).await; } diff --git a/rust/agama-dbus-server/tests/network.rs b/rust/agama-dbus-server/tests/network.rs index 37d404210a..4db36e95d7 100644 --- a/rust/agama-dbus-server/tests/network.rs +++ b/rust/agama-dbus-server/tests/network.rs @@ -36,7 +36,7 @@ async fn test_read_connections() -> Result<(), Box> { let state = NetworkState::new(vec![device], vec![eth0]); let adapter = NetworkTestAdapter(state); - let _service = NetworkService::start(&server.connection(), adapter).await?; + NetworkService::start(&server.connection(), adapter).await?; server.request_name().await?; let client = NetworkClient::new(server.connection()).await?; @@ -54,7 +54,7 @@ async fn test_add_connection() -> Result<(), Box> { let adapter = NetworkTestAdapter(NetworkState::default()); - let _service = NetworkService::start(&server.connection(), adapter).await?; + NetworkService::start(&server.connection(), adapter).await?; server.request_name().await?; let client = NetworkClient::new(server.connection().clone()).await?; @@ -101,7 +101,7 @@ async fn test_update_connection() -> Result<(), Box> { let state = NetworkState::new(vec![device], vec![eth0]); let adapter = NetworkTestAdapter(state); - let _service = NetworkService::start(&server.connection(), adapter).await?; + NetworkService::start(&server.connection(), adapter).await?; server.request_name().await?; let client = NetworkClient::new(server.connection()).await?; From e5152ecbab0226527464f2b6dccb4ffbccc9bea8 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 16:41:33 +0100 Subject: [PATCH 11/33] and final clippy suggestions --- rust/agama-cli/src/logs.rs | 4 ++-- rust/agama-cli/src/main.rs | 1 - rust/agama-dbus-server/src/locale/locale.rs | 5 +---- rust/agama-dbus-server/src/main.rs | 1 - rust/agama-dbus-server/src/network/nm/dbus.rs | 17 ++++------------- .../src/keyboard/xkb_config_registry.rs | 4 ++-- rust/agama-locale-data/src/lib.rs | 3 +-- 7 files changed, 10 insertions(+), 25 deletions(-) diff --git a/rust/agama-cli/src/logs.rs b/rust/agama-cli/src/logs.rs index 027da2c9a2..92f989cb99 100644 --- a/rust/agama-cli/src/logs.rs +++ b/rust/agama-cli/src/logs.rs @@ -258,7 +258,7 @@ impl LogItem for LogCmd { }; file_name.retain(|c| c != ' '); - self.dst_path.as_path().join(format!("{}", file_name)) + self.dst_path.as_path().join(&file_name) } fn store(&self) -> Result<(), io::Error> { @@ -416,7 +416,7 @@ fn store(options: LogOptions) -> Result<(), io::Error> { Err(_e) => "[Failed]", }; - showln(verbose, format!("{}", res).as_str()); + showln(verbose, res.to_string().as_str()); } compress_logs(&tmp_dir, &result) diff --git a/rust/agama-cli/src/main.rs b/rust/agama-cli/src/main.rs index 866e4275d2..52a3fa4a89 100644 --- a/rust/agama-cli/src/main.rs +++ b/rust/agama-cli/src/main.rs @@ -25,7 +25,6 @@ use std::{ thread::sleep, time::Duration, }; -use tokio; #[derive(Parser)] #[command(name = "agama", version, about, long_about = None)] diff --git a/rust/agama-dbus-server/src/locale/locale.rs b/rust/agama-dbus-server/src/locale/locale.rs index 2bfba9aab7..a56919ea0a 100644 --- a/rust/agama-dbus-server/src/locale/locale.rs +++ b/rust/agama-dbus-server/src/locale/locale.rs @@ -120,10 +120,7 @@ mod tests { db.read("de").unwrap(); let found_locales = db.entries(); let spanish: LocaleCode = "es_ES".try_into().unwrap(); - let found = found_locales - .iter() - .find(|l| l.code == spanish) - .unwrap(); + let found = found_locales.iter().find(|l| l.code == spanish).unwrap(); assert_eq!(&found.language, "Spanisch"); assert_eq!(&found.territory, "Spanien"); } diff --git a/rust/agama-dbus-server/src/main.rs b/rust/agama-dbus-server/src/main.rs index e8dd97d73a..c890f5db71 100644 --- a/rust/agama-dbus-server/src/main.rs +++ b/rust/agama-dbus-server/src/main.rs @@ -5,7 +5,6 @@ use anyhow::Context; use log::{self, LevelFilter}; use std::future::pending; - const ADDRESS: &str = "unix:path=/run/agama/bus"; const SERVICE_NAME: &str = "org.opensuse.Agama1"; diff --git a/rust/agama-dbus-server/src/network/nm/dbus.rs b/rust/agama-dbus-server/src/network/nm/dbus.rs index 5eade2265a..e6d7a56900 100644 --- a/rust/agama-dbus-server/src/network/nm/dbus.rs +++ b/rust/agama-dbus-server/src/network/nm/dbus.rs @@ -104,10 +104,7 @@ pub fn merge_dbus_connections<'a>( /// * `conn`: connection represented as a NestedHash. fn cleanup_dbus_connection(conn: &mut NestedHash) { if let Some(connection) = conn.get_mut("connection") { - if connection - .get("interface-name") - .is_some_and(is_empty_value) - { + if connection.get("interface-name").is_some_and(is_empty_value) { connection.remove("interface-name"); } } @@ -237,19 +234,13 @@ fn wireless_config_to_dbus(conn: &WirelessConnection) -> NestedHash { /// /// * `match_config`: MatchConfig to convert. fn match_config_to_dbus(match_config: &MatchConfig) -> HashMap<&str, zvariant::Value> { - let drivers: Value = match_config - .driver.to_vec() - .into(); + let drivers: Value = match_config.driver.to_vec().into(); - let kernels: Value = match_config - .kernel.to_vec() - .into(); + let kernels: Value = match_config.kernel.to_vec().into(); let paths: Value = match_config.path.to_vec().into(); - let interfaces: Value = match_config - .interface.to_vec() - .into(); + let interfaces: Value = match_config.interface.to_vec().into(); HashMap::from([ ("driver", drivers), diff --git a/rust/agama-locale-data/src/keyboard/xkb_config_registry.rs b/rust/agama-locale-data/src/keyboard/xkb_config_registry.rs index a1bdd07cb6..a462f5cffe 100644 --- a/rust/agama-locale-data/src/keyboard/xkb_config_registry.rs +++ b/rust/agama-locale-data/src/keyboard/xkb_config_registry.rs @@ -6,7 +6,7 @@ use quick_xml::de::from_str; use serde::Deserialize; use std::{error::Error, fs}; -const DB_PATH: &'static str = "/usr/share/X11/xkb/rules/base.xml"; +const DB_PATH: &str = "/usr/share/X11/xkb/rules/base.xml"; /// X Keyboard Configuration Database #[derive(Deserialize, Debug)] @@ -20,7 +20,7 @@ impl XkbConfigRegistry { /// /// - `path`: database path. pub fn from(path: &str) -> Result> { - let contents = fs::read_to_string(&path)?; + let contents = fs::read_to_string(path)?; Ok(from_str(&contents)?) } diff --git a/rust/agama-locale-data/src/lib.rs b/rust/agama-locale-data/src/lib.rs index e1a48914d0..8b9dfcee4f 100644 --- a/rust/agama-locale-data/src/lib.rs +++ b/rust/agama-locale-data/src/lib.rs @@ -150,7 +150,6 @@ mod tests { let localized = get_timezone_parts() .unwrap() .localize_timezones("de", &timezones); - let _res: Vec<(String, String)> = - timezones.into_iter().zip(localized.into_iter()).collect(); + let _res: Vec<(String, String)> = timezones.into_iter().zip(localized).collect(); } } From 7b6ca592045de8c82ed723b4473a8f713e29a572 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 16:50:18 +0100 Subject: [PATCH 12/33] one more suggestion applied --- rust/agama-derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/agama-derive/src/lib.rs b/rust/agama-derive/src/lib.rs index 7f5a1a2d91..020d4d461f 100644 --- a/rust/agama-derive/src/lib.rs +++ b/rust/agama-derive/src/lib.rs @@ -293,7 +293,7 @@ fn parse_setting_fields(fields: Vec<&syn::Field>) -> SettingFieldsList { SettingFieldsList(settings) } -fn quote_fields_aliases(nested_fields: &Vec<&SettingField>) -> Vec { +fn quote_fields_aliases(nested_fields: &[&SettingField]) -> Vec { nested_fields .iter() .map(|f| { From 4d75eec9b4c64af217d9df6a2765d3e2abc0c7cb Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 21:41:27 +0100 Subject: [PATCH 13/33] fix name of registration email to match schema --- rust/agama-lib/src/product/settings.rs | 2 +- rust/agama-lib/src/product/store.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/product/settings.rs b/rust/agama-lib/src/product/settings.rs index dff0c01c8e..9cda158ff5 100644 --- a/rust/agama-lib/src/product/settings.rs +++ b/rust/agama-lib/src/product/settings.rs @@ -10,5 +10,5 @@ pub struct ProductSettings { /// ID of the product to install (e.g., "ALP", "Tumbleweed", etc.) pub id: Option, pub registration_code: Option, - pub email: Option, + pub registration_email: Option, } diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index f2559e1d34..f0cd582d39 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -27,7 +27,7 @@ impl<'a> ProductStore<'a> { Ok(ProductSettings { id: Some(product), registration_code: Some(registration_code), - email: Some(email), + registration_email: Some(email), }) } @@ -42,7 +42,7 @@ impl<'a> ProductStore<'a> { } } if let Some(reg_code) = &settings.registration_code { - let email = settings.email.clone().unwrap_or_default(); + let email = settings.registration_email.clone().unwrap_or_default(); self.product_client.register(reg_code, &email).await?; probe = true; } From e980cbed70eca0856e086f9b6ce04a08526e393f Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 7 Dec 2023 21:44:59 +0100 Subject: [PATCH 14/33] avoid unnecessary clone --- rust/agama-lib/src/product/store.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index f0cd582d39..c0ae063b3c 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -42,8 +42,11 @@ impl<'a> ProductStore<'a> { } } if let Some(reg_code) = &settings.registration_code { - let email = settings.registration_email.clone().unwrap_or_default(); - self.product_client.register(reg_code, &email).await?; + if let Some(email) = &settings.registration_email { + self.product_client.register(reg_code, email).await?; + } else { + self.product_client.register(reg_code, "").await?; + } probe = true; } From 6ffe581e0b1fc2bb3781e8f807c8a25da071b3ef Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 10:22:21 +0100 Subject: [PATCH 15/33] Apply suggestions from code review Co-authored-by: Martin Vidner --- rust/agama-lib/src/product/client.rs | 2 +- rust/agama-lib/src/product/settings.rs | 2 +- rust/agama-lib/src/product/store.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index 8d0e090ccb..0413096df7 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -54,7 +54,7 @@ impl<'a> ProductClient<'a> { Ok(products) } - /// Returns the selected product to install + /// Returns the id of the selected product to install pub async fn product(&self) -> Result { Ok(self.product_proxy.selected_product().await?) } diff --git a/rust/agama-lib/src/product/settings.rs b/rust/agama-lib/src/product/settings.rs index 9cda158ff5..647801470e 100644 --- a/rust/agama-lib/src/product/settings.rs +++ b/rust/agama-lib/src/product/settings.rs @@ -1,4 +1,4 @@ -//! Representation of the software settings +//! Representation of the product settings use agama_settings::Settings; use serde::{Deserialize, Serialize}; diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index c0ae063b3c..30a8d524c2 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -1,11 +1,11 @@ -//! Implements the store for the storage settings. +//! Implements the store for the product settings. use super::{ProductClient, ProductSettings}; use crate::error::ServiceError; use crate::manager::ManagerClient; use zbus::Connection; -/// Loads and stores the software settings from/to the D-Bus service. +/// Loads and stores the product settings from/to the D-Bus service. pub struct ProductStore<'a> { product_client: ProductClient<'a>, manager_client: ManagerClient<'a>, From 3689a22e9e0fc7ead682747c5270c4df20f5a006 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 10:23:01 +0100 Subject: [PATCH 16/33] implement passing email --- rust/agama-lib/src/product.rs | 2 +- rust/agama-lib/src/product/client.rs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/product.rs b/rust/agama-lib/src/product.rs index a7054785f1..e85173f6c9 100644 --- a/rust/agama-lib/src/product.rs +++ b/rust/agama-lib/src/product.rs @@ -1,4 +1,4 @@ -//! Implements support for handling the users settings +//! Implements support for handling the product settings mod client; mod proxies; diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index 0413096df7..d62ae7a872 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -86,8 +86,11 @@ impl<'a> ProductClient<'a> { } /// register product - pub async fn register(&self, code: &str, _email: &str) -> Result<(), ServiceError> { - // TODO: handle email + pub async fn register(&self, code: &str, email: &str) -> Result<(), ServiceError> { + let mut options = HashMap::new(); + if !email.is_empty() { + options.insert("Email", email); + } self.registration_proxy .register(code, HashMap::new()) .await?; From 8741ad6d23cf17310a1a6d3117a5bd785d1d8040 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 10:25:21 +0100 Subject: [PATCH 17/33] changes --- rust/package/agama-cli.changes | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/rust/package/agama-cli.changes b/rust/package/agama-cli.changes index 0a6e8d573f..ee76c4e5b9 100644 --- a/rust/package/agama-cli.changes +++ b/rust/package/agama-cli.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri Dec 8 09:23:09 UTC 2023 - Josef Reidinger + +- Change the config in a way that: (gh#openSUSE/agama#919) + 1. product is moved to own section and is now under product.id + 2. in product section is now also registrationCode and registrationEmail + 3. in software section is now patterns to select patterns to install +- adapt profile.schema according to above changes + ------------------------------------------------------------------- Tue Dec 5 11:18:41 UTC 2023 - Jorik Cronenberg From 3d2aad10f3191a7744de8078653f37f15d7e129c Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 15:14:10 +0100 Subject: [PATCH 18/33] fix email handling --- rust/agama-lib/src/product/client.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index d62ae7a872..a2e927e6f9 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -87,13 +87,11 @@ impl<'a> ProductClient<'a> { /// register product pub async fn register(&self, code: &str, email: &str) -> Result<(), ServiceError> { - let mut options = HashMap::new(); + let mut options: HashMap<&str, zbus::zvariant::Value> = HashMap::new(); if !email.is_empty() { - options.insert("Email", email); + options.insert("Email", zbus::zvariant::Value::new(email)); } - self.registration_proxy - .register(code, HashMap::new()) - .await?; + self.registration_proxy.register(code, options).await?; Ok(()) } } From 5a8cba63ac53596a8b882b24a4899e76a1b4cf2b Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 21:55:59 +0100 Subject: [PATCH 19/33] report properly registration errors --- rust/agama-lib/src/error.rs | 2 ++ rust/agama-lib/src/product/client.rs | 5 ++--- rust/agama-lib/src/product/store.rs | 8 ++++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/rust/agama-lib/src/error.rs b/rust/agama-lib/src/error.rs index 7124e00cbb..b3c72aec30 100644 --- a/rust/agama-lib/src/error.rs +++ b/rust/agama-lib/src/error.rs @@ -16,6 +16,8 @@ pub enum ServiceError { Anyhow(#[from] anyhow::Error), #[error("Wrong user parameters: '{0:?}'")] WrongUser(Vec), + #[error("Registration failed: '{0}'")] + FailedRegistration(String), #[error("Error: {0}")] UnsuccessfulAction(String), } diff --git a/rust/agama-lib/src/product/client.rs b/rust/agama-lib/src/product/client.rs index a2e927e6f9..106166b621 100644 --- a/rust/agama-lib/src/product/client.rs +++ b/rust/agama-lib/src/product/client.rs @@ -86,12 +86,11 @@ impl<'a> ProductClient<'a> { } /// register product - pub async fn register(&self, code: &str, email: &str) -> Result<(), ServiceError> { + pub async fn register(&self, code: &str, email: &str) -> Result<(u32, String), ServiceError> { let mut options: HashMap<&str, zbus::zvariant::Value> = HashMap::new(); if !email.is_empty() { options.insert("Email", zbus::zvariant::Value::new(email)); } - self.registration_proxy.register(code, options).await?; - Ok(()) + Ok(self.registration_proxy.register(code, options).await?) } } diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 30a8d524c2..289da59f58 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -42,10 +42,14 @@ impl<'a> ProductStore<'a> { } } if let Some(reg_code) = &settings.registration_code { + let (result, message); if let Some(email) = &settings.registration_email { - self.product_client.register(reg_code, email).await?; + (result, message) = self.product_client.register(reg_code, email).await?; } else { - self.product_client.register(reg_code, "").await?; + (result, message) = self.product_client.register(reg_code, "").await?; + }; + if result != 0 { + return Err(ServiceError::FailedRegistration(message)); } probe = true; } From d4b2a87f1223cd80b52be999fac2da57b9854c8b Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 22:07:11 +0100 Subject: [PATCH 20/33] remove unnecessary ending --- rust/agama-lib/src/product/store.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 289da59f58..1d04514687 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -47,7 +47,7 @@ impl<'a> ProductStore<'a> { (result, message) = self.product_client.register(reg_code, email).await?; } else { (result, message) = self.product_client.register(reg_code, "").await?; - }; + } if result != 0 { return Err(ServiceError::FailedRegistration(message)); } From 69802291cd8a2842bc00a1cb5671d3236daed6f6 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 22:17:11 +0100 Subject: [PATCH 21/33] Apply suggestions from code review Co-authored-by: Martin Vidner --- rust/agama-lib/src/software/client.rs | 2 +- rust/agama-lib/src/software/settings.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index f45e01dad9..aaf4d83a50 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -53,7 +53,7 @@ impl<'a> SoftwareClient<'a> { Ok(patterns) } - /// Returns the selected patterns by user + /// Returns the ids of patterns selected by user pub async fn user_selected_patterns(&self) -> Result, ServiceError> { const USER_SELECTED: u8 = 0; let patterns: Vec = self diff --git a/rust/agama-lib/src/software/settings.rs b/rust/agama-lib/src/software/settings.rs index 5412146938..a2dba395ee 100644 --- a/rust/agama-lib/src/software/settings.rs +++ b/rust/agama-lib/src/software/settings.rs @@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Settings, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SoftwareSettings { - /// List of patterns to install. If not specified use default. + /// List of patterns to install. If empty use default. #[settings(collection)] pub patterns: Vec, } From b75a6e14a2fd1108aa6cf8bf0bba8c2fef8e25dc Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 8 Dec 2023 22:22:46 +0100 Subject: [PATCH 22/33] document list of patterns dbus call --- doc/dbus/org.opensuse.Agama.Software1.doc.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/dbus/org.opensuse.Agama.Software1.doc.xml b/doc/dbus/org.opensuse.Agama.Software1.doc.xml index bacbe87d94..b9e5508aec 100644 --- a/doc/dbus/org.opensuse.Agama.Software1.doc.xml +++ b/doc/dbus/org.opensuse.Agama.Software1.doc.xml @@ -4,8 +4,25 @@ + + + From cef4857d34113d6091ff8124eed2c7a1d9650fe5 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 11 Dec 2023 08:54:07 +0100 Subject: [PATCH 23/33] Return SCC error details, don't just log them Before: "Connection to registration server failed" After: "Connection to registration server failed: Unknown Registration Code" --- service/lib/agama/dbus/software/product.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/agama/dbus/software/product.rb b/service/lib/agama/dbus/software/product.rb index 6c94418a9d..ba983232ec 100644 --- a/service/lib/agama/dbus/software/product.rb +++ b/service/lib/agama/dbus/software/product.rb @@ -283,7 +283,7 @@ def connect_result(first_error_code: 1, &block) def connect_result_from_error(error, error_code, details = nil) logger.error("Error connecting to registration server: #{error}") - description = "Connection to registration server failed" + description = "Connection to registration server failed: #{error}" description += " (#{details})" if details [error_code, description] From a3c3140d36bd2044e8b6580a1f93e263bebb2889 Mon Sep 17 00:00:00 2001 From: Martin Vidner Date: Mon, 11 Dec 2023 09:45:02 +0100 Subject: [PATCH 24/33] 'Product does not require registration' will not fail the whole thing --- rust/agama-lib/src/product/store.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rust/agama-lib/src/product/store.rs b/rust/agama-lib/src/product/store.rs index 1d04514687..5ed3e72745 100644 --- a/rust/agama-lib/src/product/store.rs +++ b/rust/agama-lib/src/product/store.rs @@ -48,7 +48,9 @@ impl<'a> ProductStore<'a> { } else { (result, message) = self.product_client.register(reg_code, "").await?; } - if result != 0 { + // FIXME: name the magic numbers. 3 is Registration not required + // FIXME: well don't register when not required (no regcode in profile) + if result != 0 && result != 3 { return Err(ServiceError::FailedRegistration(message)); } probe = true; From 9861060e15d7407a741dc1ee74e68276f6f42e79 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Tue, 12 Dec 2023 21:20:56 +0100 Subject: [PATCH 25/33] add error values for pattern selection --- service/lib/agama/dbus/software/manager.rb | 6 +++--- service/lib/agama/software/manager.rb | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/service/lib/agama/dbus/software/manager.rb b/service/lib/agama/dbus/software/manager.rb index a22729c3eb..e3d835ea6f 100644 --- a/service/lib/agama/dbus/software/manager.rb +++ b/service/lib/agama/dbus/software/manager.rb @@ -87,9 +87,9 @@ def issues # 1 for auto selected. Can be extended in future e.g. for mandatory patterns dbus_reader_attr_accessor :selected_patterns, "a{sy}" - dbus_method(:AddPattern, "in id:s") { |p| backend.add_pattern(p) } - dbus_method(:RemovePattern, "in id:s") { |p| backend.remove_pattern(p) } - dbus_method(:SetUserPatterns, "in ids:as") { |ids| backend.user_patterns = ids } + dbus_method(:AddPattern, "in id:s, out result:b") { |p| backend.add_pattern(p) } + dbus_method(:RemovePattern, "in id:s, out result:b") { |p| backend.remove_pattern(p) } + dbus_method(:SetUserPatterns, "in ids:as, out wrong:as") { |ids| backend.assign_patterns(ids) } dbus_method :ProvisionsSelected, "in Provisions:as, out Result:ab" do |provisions| [provisions.map { |p| backend.provision_selected?(p) }] diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index 74e757a6ff..7869518f32 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -223,7 +223,8 @@ def patterns(filtered) end def add_pattern(id) - # TODO: error handling + return false unless pattern_exist?(id) + res = Yast::Pkg.ResolvableInstall(id, :pattern) logger.info "Adding pattern #{res.inspect}" Yast::PackagesProposal.AddResolvables(PROPOSAL_ID, :pattern, [id]) @@ -231,10 +232,13 @@ def add_pattern(id) res = Yast::Pkg.PkgSolve(unused = true) logger.info "Solver run #{res.inspect}" selected_patterns_changed + + true end def remove_pattern(id) - # TODO: error handling + return false unless pattern_exist?(id) + res = Yast::Pkg.ResolvableNeutral(id, :pattern, force = false) logger.info "Removing pattern #{res.inspect}" Yast::PackagesProposal.RemoveResolvables(PROPOSAL_ID, :pattern, [id]) @@ -242,9 +246,14 @@ def remove_pattern(id) res = Yast::Pkg.PkgSolve(unused = true) logger.info "Solver run #{res.inspect}" selected_patterns_changed + + true end - def user_patterns=(ids) + def assign_patterns(ids) + wrong_patterns = ids.reject { |p| pattern_exist?(id) } + return wrong_patterns unless wrong_patterns.empty? + user_patterns = Yast::PackagesProposal.GetResolvables(PROPOSAL_ID, :pattern) user_patterns.each { |p| Yast::Pkg.ResolvableNeutral(p, :pattern, force = false) } Yast::PackagesProposal.SetResolvables(PROPOSAL_ID, :pattern, ids) @@ -254,6 +263,8 @@ def user_patterns=(ids) res = Yast::Pkg.PkgSolve(unused = true) logger.info "Solver run #{res.inspect}" selected_patterns_changed + + [] end # @return [Array,Array] returns pair of arrays where the first one @@ -479,6 +490,10 @@ def missing_registration? registration.reg_code.nil? && registration.requirement == Agama::Registration::Requirement::MANDATORY end + + def pattern_exist?(pattern_name) + !Y2Packager::Resolvable.find(kind: :pattern, name: pattern_name).empty? + end end end end From 915ace5a3a7daddee98414d467c9ca74ef53ced2 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Tue, 12 Dec 2023 21:26:35 +0100 Subject: [PATCH 26/33] document dbus API change --- doc/dbus/org.opensuse.Agama.Software1.doc.xml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/doc/dbus/org.opensuse.Agama.Software1.doc.xml b/doc/dbus/org.opensuse.Agama.Software1.doc.xml index b9e5508aec..9cc325862a 100644 --- a/doc/dbus/org.opensuse.Agama.Software1.doc.xml +++ b/doc/dbus/org.opensuse.Agama.Software1.doc.xml @@ -25,14 +25,47 @@ --> + + + + + + + + + + + + From 98998668ba317efe88271c7eb213ab1de903f508 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 14:02:50 +0100 Subject: [PATCH 27/33] regenerate proxy to fit new return values --- rust/agama-lib/src/software/proxies.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/agama-lib/src/software/proxies.rs b/rust/agama-lib/src/software/proxies.rs index 8fc081b3c6..a37cc1b341 100644 --- a/rust/agama-lib/src/software/proxies.rs +++ b/rust/agama-lib/src/software/proxies.rs @@ -10,7 +10,7 @@ use zbus::dbus_proxy; )] trait Software1 { /// AddPattern method - fn add_pattern(&self, id: &str) -> zbus::Result<()>; + fn add_pattern(&self, id: &str) -> zbus::Result; /// Finish method fn finish(&self) -> zbus::Result<()>; @@ -37,10 +37,10 @@ trait Software1 { fn provisions_selected(&self, provisions: &[&str]) -> zbus::Result>; /// RemovePattern method - fn remove_pattern(&self, id: &str) -> zbus::Result<()>; + fn remove_pattern(&self, id: &str) -> zbus::Result; /// SetUserPatterns method - fn set_user_patterns(&self, ids: &[&str]) -> zbus::Result<()>; + fn set_user_patterns(&self, ids: &[&str]) -> zbus::Result>; /// UsedDiskSpace method fn used_disk_space(&self) -> zbus::Result; From 607cfe209383b3d14b6593994b78f697abcc7455 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 14:48:57 +0100 Subject: [PATCH 28/33] handle wrong patterns and update bus --- doc/dbus/bus/org.opensuse.Agama.Software1.bus.xml | 3 +++ rust/agama-lib/src/error.rs | 2 ++ rust/agama-lib/src/software/client.rs | 8 ++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/doc/dbus/bus/org.opensuse.Agama.Software1.bus.xml b/doc/dbus/bus/org.opensuse.Agama.Software1.bus.xml index 9535bb3c0f..525ce9d6fb 100644 --- a/doc/dbus/bus/org.opensuse.Agama.Software1.bus.xml +++ b/doc/dbus/bus/org.opensuse.Agama.Software1.bus.xml @@ -35,12 +35,15 @@ + + + diff --git a/rust/agama-lib/src/error.rs b/rust/agama-lib/src/error.rs index b3c72aec30..19002179b3 100644 --- a/rust/agama-lib/src/error.rs +++ b/rust/agama-lib/src/error.rs @@ -18,6 +18,8 @@ pub enum ServiceError { WrongUser(Vec), #[error("Registration failed: '{0}'")] FailedRegistration(String), + #[error("Failed to find these patterns: '{0:?}'")] + UnknownPatterns(Vec), #[error("Error: {0}")] UnsuccessfulAction(String), } diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index aaf4d83a50..62c0fe6796 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -70,9 +70,13 @@ impl<'a> SoftwareClient<'a> { /// Selects patterns by user pub async fn select_patterns(&self, patterns: &[String]) -> Result<(), ServiceError> { let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); - self.software_proxy + let wrong_patterns = self.software_proxy .set_user_patterns(patterns.as_slice()) .await?; - Ok(()) + if wrong_patterns.is_empty() { + Err(ServiceError::UnknownPatterns(wrong_patterns)) + } else { + Ok(()) + } } } From e84aadaf1836910b658bfc04891837b8fd45fafc Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 16:36:15 +0100 Subject: [PATCH 29/33] fix typo --- service/lib/agama/software/manager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/agama/software/manager.rb b/service/lib/agama/software/manager.rb index 7869518f32..a06e780b14 100644 --- a/service/lib/agama/software/manager.rb +++ b/service/lib/agama/software/manager.rb @@ -251,7 +251,7 @@ def remove_pattern(id) end def assign_patterns(ids) - wrong_patterns = ids.reject { |p| pattern_exist?(id) } + wrong_patterns = ids.reject { |p| pattern_exist?(p) } return wrong_patterns unless wrong_patterns.empty? user_patterns = Yast::PackagesProposal.GetResolvables(PROPOSAL_ID, :pattern) From f32952cfd4eac27d8b975b08c5080fb5f27fb452 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 16:41:32 +0100 Subject: [PATCH 30/33] fix dbus marshalling --- service/lib/agama/dbus/software/manager.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/service/lib/agama/dbus/software/manager.rb b/service/lib/agama/dbus/software/manager.rb index e3d835ea6f..9ca3ea8eb2 100644 --- a/service/lib/agama/dbus/software/manager.rb +++ b/service/lib/agama/dbus/software/manager.rb @@ -89,7 +89,7 @@ def issues dbus_method(:AddPattern, "in id:s, out result:b") { |p| backend.add_pattern(p) } dbus_method(:RemovePattern, "in id:s, out result:b") { |p| backend.remove_pattern(p) } - dbus_method(:SetUserPatterns, "in ids:as, out wrong:as") { |ids| backend.assign_patterns(ids) } + dbus_method(:SetUserPatterns, "in ids:as, out wrong:as") { |ids| [backend.assign_patterns(ids)] } dbus_method :ProvisionsSelected, "in Provisions:as, out Result:ab" do |provisions| [provisions.map { |p| backend.provision_selected?(p) }] From 9e5ed6861d6fcf660b8a09afd7bb41792385ab65 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 21:44:48 +0100 Subject: [PATCH 31/33] fix condition --- rust/agama-lib/src/software/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index 62c0fe6796..b1ef923b46 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -73,7 +73,7 @@ impl<'a> SoftwareClient<'a> { let wrong_patterns = self.software_proxy .set_user_patterns(patterns.as_slice()) .await?; - if wrong_patterns.is_empty() { + if !wrong_patterns.is_empty() { Err(ServiceError::UnknownPatterns(wrong_patterns)) } else { Ok(()) From d34f255750a1bb37b87a713a85bf1edd47e9a266 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Wed, 13 Dec 2023 22:10:01 +0100 Subject: [PATCH 32/33] make formatting happy --- rust/agama-lib/src/software/client.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rust/agama-lib/src/software/client.rs b/rust/agama-lib/src/software/client.rs index b1ef923b46..0670467b02 100644 --- a/rust/agama-lib/src/software/client.rs +++ b/rust/agama-lib/src/software/client.rs @@ -70,7 +70,8 @@ impl<'a> SoftwareClient<'a> { /// Selects patterns by user pub async fn select_patterns(&self, patterns: &[String]) -> Result<(), ServiceError> { let patterns: Vec<&str> = patterns.iter().map(AsRef::as_ref).collect(); - let wrong_patterns = self.software_proxy + let wrong_patterns = self + .software_proxy .set_user_patterns(patterns.as_slice()) .await?; if !wrong_patterns.is_empty() { From 9b8f086212a3076c7ac6a11d0bafd4cef553c7ea Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 14 Dec 2023 13:49:45 +0100 Subject: [PATCH 33/33] Apply suggestions from code review Co-authored-by: Martin Vidner --- doc/dbus/org.opensuse.Agama.Software1.doc.xml | 2 +- rust/agama-lib/src/error.rs | 2 +- rust/package/agama-cli.changes | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/dbus/org.opensuse.Agama.Software1.doc.xml b/doc/dbus/org.opensuse.Agama.Software1.doc.xml index 9cc325862a..ed2dca4c0f 100644 --- a/doc/dbus/org.opensuse.Agama.Software1.doc.xml +++ b/doc/dbus/org.opensuse.Agama.Software1.doc.xml @@ -54,7 +54,7 @@