From 2725a7b7e606c704bbdbec4d1cf2c0ee4bb0a375 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 30 May 2024 07:25:35 +0200 Subject: [PATCH 1/9] document arguments for import command --- rust/agama-cli/src/profile.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index fdcba596c3..cf8e6c572b 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -26,9 +26,14 @@ pub enum ProfileCommands { /// This is top level command that do all autoinstallation processing beside starting /// installation. Unless there is a need to inject additional commands between processing /// use this command instead of set of underlying commands. - /// Optional dir argument is location where profile is processed. Useful for debugging - /// if something goes wrong. - Import { url: String, dir: Option }, + Import { + /// URL where profile is located. Supported schemas are all that download supports and additionally + /// autoyast specific ones. Supported files are json, jsonnet, sh for agama profiles and erb, xml, directory + /// for autoyast support. + url: String, + /// Specific directory where all processing happens. If not specific temporary directory is used + dir: Option, + }, } fn download(url: &str, mut out_fd: impl Write) -> anyhow::Result<()> { From a0392f11cf919464e329bbda9ad6ca884e5ea035 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 30 May 2024 09:04:48 +0200 Subject: [PATCH 2/9] introduce separate download command with no extra autoyast processing --- rust/Cargo.lock | 1 + rust/agama-cli/Cargo.toml | 1 + rust/agama-cli/src/commands.rs | 12 ++++++++++++ rust/agama-cli/src/main.rs | 16 ++++++++++++++++ rust/agama-lib/Cargo.toml | 3 ++- 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index dba9fcb2f4..645021b98c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -28,6 +28,7 @@ dependencies = [ "clap", "console", "convert_case", + "curl", "fs_extra", "home", "indicatif", diff --git a/rust/agama-cli/Cargo.toml b/rust/agama-cli/Cargo.toml index bcfcab6dd0..fcfce9a52d 100644 --- a/rust/agama-cli/Cargo.toml +++ b/rust/agama-cli/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] clap = { version = "4.1.4", features = ["derive", "wrap_help"] } +curl = { version = "0.4.44", features = ["protocol-ftp"] } agama-lib = { path="../agama-lib" } agama-settings = { path="../agama-settings" } serde = { version = "1.0.152" } diff --git a/rust/agama-cli/src/commands.rs b/rust/agama-cli/src/commands.rs index a248a0de49..954b3c484c 100644 --- a/rust/agama-cli/src/commands.rs +++ b/rust/agama-cli/src/commands.rs @@ -72,4 +72,16 @@ pub enum Commands { /// not affect the root user. #[command(subcommand)] Auth(AuthCommands), + + /// Download file from given URL + /// + /// Purpose of this command is to allow download from all supported schemas. + /// It can be used to download additional scripts, configuration files and so on. + /// For agama autoinstallation profiles it can be also used, but unless additional processing is required + /// the "agama profile import" is recommended. + /// For autoyast conversion use directly "agama profile autoyast". + Download { + /// URL pointing to file for download + url: String, + }, } diff --git a/rust/agama-cli/src/main.rs b/rust/agama-cli/src/main.rs index 4815d42777..9b1f2f3abc 100644 --- a/rust/agama-cli/src/main.rs +++ b/rust/agama-cli/src/main.rs @@ -17,12 +17,14 @@ use agama_lib::progress::ProgressMonitor; use auth::run as run_auth_cmd; use commands::Commands; use config::run as run_config_cmd; +use curl::easy::Easy; use logs::run as run_logs_cmd; use printers::Format; use profile::run as run_profile_cmd; use progress::InstallerProgress; use questions::run as run_questions_cmd; use std::{ + io::Write, process::{ExitCode, Termination}, thread::sleep, time::Duration, @@ -119,6 +121,19 @@ async fn wait_for_services(manager: &ManagerClient<'_>) -> Result<(), ServiceErr Ok(()) } +fn read_from_url(url: &str) -> anyhow::Result<()> { + let mut handle = Easy::new(); + handle.url(url)?; + + let mut transfer = handle.transfer(); + transfer.write_function(|buf| + // unwrap here is ok, as we want to kill download if we failed to write to stdout for whatever reason + Ok(std::io::stdout().write(buf).unwrap()))?; + transfer.perform()?; + + Ok(()) +} + async fn build_manager<'a>() -> anyhow::Result> { let conn = agama_lib::connection().await?; Ok(ManagerClient::new(conn).await?) @@ -144,6 +159,7 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> { Commands::Questions(subcommand) => run_questions_cmd(subcommand).await, Commands::Logs(subcommand) => run_logs_cmd(subcommand).await, Commands::Auth(subcommand) => run_auth_cmd(subcommand).await, + Commands::Download { url } => read_from_url(&url), } } diff --git a/rust/agama-lib/Cargo.toml b/rust/agama-lib/Cargo.toml index 8bab6d10a4..dc0020c419 100644 --- a/rust/agama-lib/Cargo.toml +++ b/rust/agama-lib/Cargo.toml @@ -10,7 +10,6 @@ agama-settings = { path="../agama-settings" } anyhow = "1.0" async-trait = "0.1.77" cidr = { version = "0.2.2", features = ["serde"] } -curl = { version = "0.4.44", features = ["protocol-ftp"] } futures-util = "0.3.29" jsonschema = { version = "0.16.1", default-features = false } log = "0.4" @@ -25,3 +24,5 @@ tokio-stream = "0.1.14" url = "2.5.0" utoipa = "4.2.0" zbus = { version = "3", default-features = false, features = ["tokio"] } +# Needed to define curl error in profile errors +curl = { version = "0.4.44", features = ["protocol-ftp"] } From dc001ff0c3b6cf88b9148bff81887febb58de087 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 30 May 2024 15:48:45 +0200 Subject: [PATCH 3/9] add 'agama profile autoyast' command --- rust/Cargo.lock | 1 + rust/agama-cli/Cargo.toml | 1 + rust/agama-cli/src/main.rs | 17 +----------- rust/agama-cli/src/profile.rs | 50 ++++++++++++++++++++++++++--------- rust/agama-lib/src/profile.rs | 37 ++++++++------------------ 5 files changed, 51 insertions(+), 55 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 645021b98c..a9ac17634e 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -42,6 +42,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", + "url", "zbus", ] diff --git a/rust/agama-cli/Cargo.toml b/rust/agama-cli/Cargo.toml index fcfce9a52d..772ba7e6e1 100644 --- a/rust/agama-cli/Cargo.toml +++ b/rust/agama-cli/Cargo.toml @@ -29,6 +29,7 @@ async-trait = "0.1.77" reqwest = { version = "0.11", features = ["json"] } home = "0.5.9" rpassword = "7.3.1" +url = "2.5.0" [[bin]] name = "agama" diff --git a/rust/agama-cli/src/main.rs b/rust/agama-cli/src/main.rs index 9b1f2f3abc..87cf6ba4bc 100644 --- a/rust/agama-cli/src/main.rs +++ b/rust/agama-cli/src/main.rs @@ -17,14 +17,12 @@ use agama_lib::progress::ProgressMonitor; use auth::run as run_auth_cmd; use commands::Commands; use config::run as run_config_cmd; -use curl::easy::Easy; use logs::run as run_logs_cmd; use printers::Format; use profile::run as run_profile_cmd; use progress::InstallerProgress; use questions::run as run_questions_cmd; use std::{ - io::Write, process::{ExitCode, Termination}, thread::sleep, time::Duration, @@ -121,19 +119,6 @@ async fn wait_for_services(manager: &ManagerClient<'_>) -> Result<(), ServiceErr Ok(()) } -fn read_from_url(url: &str) -> anyhow::Result<()> { - let mut handle = Easy::new(); - handle.url(url)?; - - let mut transfer = handle.transfer(); - transfer.write_function(|buf| - // unwrap here is ok, as we want to kill download if we failed to write to stdout for whatever reason - Ok(std::io::stdout().write(buf).unwrap()))?; - transfer.perform()?; - - Ok(()) -} - async fn build_manager<'a>() -> anyhow::Result> { let conn = agama_lib::connection().await?; Ok(ManagerClient::new(conn).await?) @@ -159,7 +144,7 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> { Commands::Questions(subcommand) => run_questions_cmd(subcommand).await, Commands::Logs(subcommand) => run_logs_cmd(subcommand).await, Commands::Auth(subcommand) => run_auth_cmd(subcommand).await, - Commands::Download { url } => read_from_url(&url), + Commands::Download { url } => crate::profile::download(&url, std::io::stdout()), } } diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index cf8e6c572b..d8775ed9f3 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -1,6 +1,8 @@ -use agama_lib::profile::{ProfileEvaluator, ProfileReader, ProfileValidator, ValidationResult}; +use agama_lib::profile::{ProfileEvaluator, AutoyastProfile, ProfileValidator, ValidationResult}; use anyhow::Context; use clap::Subcommand; +use curl::easy::Easy; +use url::Url; use std::os::unix::process::CommandExt; use std::{ fs::File, @@ -12,8 +14,8 @@ use tempfile::TempDir; #[derive(Subcommand, Debug)] pub enum ProfileCommands { - /// Download the profile from a given location - Download { url: String }, + /// Download the autoyast profile and convert it to json + Autoyast { url: String }, /// Validate a profile using JSON Schema Validate { path: String }, @@ -36,10 +38,17 @@ pub enum ProfileCommands { }, } -fn download(url: &str, mut out_fd: impl Write) -> anyhow::Result<()> { - let reader = ProfileReader::new(url)?; - let contents = reader.read()?; - out_fd.write_all(contents.as_bytes())?; + +pub fn download(url: &str, mut out_fd: impl Write) -> anyhow::Result<()> { + let mut handle = Easy::new(); + handle.url(url)?; + + let mut transfer = handle.transfer(); + transfer.write_function(|buf| + // unwrap here is ok, as we want to kill download if we failed to write content + Ok(out_fd.write(buf).unwrap()))?; + transfer.perform()?; + Ok(()) } @@ -71,11 +80,13 @@ fn evaluate(path: String) -> anyhow::Result<()> { Ok(()) } -async fn import(url: String, dir: Option) -> anyhow::Result<()> { +async fn import(url_string: String, dir: Option) -> anyhow::Result<()> { + let url = Url::parse(&url_string)?; let tmpdir = TempDir::new()?; // TODO: create it only if dir is not passed - let output_file = if url.ends_with(".sh") { + let path = url.path(); + let output_file = if path.ends_with(".sh") { "profile.sh" - } else if url.ends_with(".jsonnet") { + } else if path.ends_with(".jsonnet") { "profile.jsonnet" } else { "profile.json" @@ -83,8 +94,14 @@ async fn import(url: String, dir: Option) -> anyhow::Result<()> { let output_dir = dir.unwrap_or_else(|| tmpdir.into_path()); let mut output_path = output_dir.join(output_file); let output_fd = File::create(output_path.clone())?; - //download profile - download(&url, output_fd)?; + if path.ends_with(".xml") || path.ends_with(".erb") || path.ends_with('/') { + // autoyast specific download and convert to json + AutoyastProfile::new(&url)?.read(output_fd)?; + } else { + // just download profile + download(&url_string, output_fd)?; + } + // exec shell scripts if output_file.ends_with(".sh") { let err = Command::new("bash") @@ -122,9 +139,16 @@ async fn import(url: String, dir: Option) -> anyhow::Result<()> { Ok(()) } +fn autoyast(url_string: String) -> anyhow::Result<()>{ + let url = Url::parse(&url_string)?; + let reader = AutoyastProfile::new(&url)?; + reader.read(std::io::stdout())?; + Ok(()) +} + pub async fn run(subcommand: ProfileCommands) -> anyhow::Result<()> { match subcommand { - ProfileCommands::Download { url } => download(&url, std::io::stdout()), + ProfileCommands::Autoyast { url } => autoyast(url), ProfileCommands::Validate { path } => validate(path), ProfileCommands::Evaluate { path } => evaluate(path), ProfileCommands::Import { url, dir } => import(url, dir).await, diff --git a/rust/agama-lib/src/profile.rs b/rust/agama-lib/src/profile.rs index e2f07df0da..4013f10f29 100644 --- a/rust/agama-lib/src/profile.rs +++ b/rust/agama-lib/src/profile.rs @@ -1,6 +1,5 @@ use crate::error::ProfileError; use anyhow::Context; -use curl::easy::Easy; use jsonschema::JSONSchema; use log::info; use serde_json; @@ -8,42 +7,28 @@ use std::{fs, io::Write, path::Path, process::Command}; use tempfile::{tempdir, TempDir}; use url::Url; -/// Downloads a profile for a given location. -pub struct ProfileReader { +/// Downloads and converts autoyast profile. +pub struct AutoyastProfile { url: Url, } -impl ProfileReader { - pub fn new(url: &str) -> anyhow::Result { - let url = Url::parse(url)?; - Ok(Self { url }) +impl AutoyastProfile { + pub fn new(url: &Url) -> anyhow::Result { + Ok(Self { url: url.clone() }) } - pub fn read(&self) -> anyhow::Result { + pub fn read(&self, mut out_fd: impl Write) -> anyhow::Result<()> { let path = self.url.path(); if path.ends_with(".xml") || path.ends_with(".erb") || path.ends_with('/') { - self.read_from_autoyast() + let content = self.read_from_autoyast()?; + out_fd.write_all(content.as_bytes())?; + Ok(()) } else { - self.read_from_url() + let msg = format!("Unsupported autoyast format at {}", self.url); + Err(anyhow::Error::msg(msg)) } } - fn read_from_url(&self) -> anyhow::Result { - let mut buf = Vec::new(); - { - let mut handle = Easy::new(); - handle.url(self.url.as_str())?; - - let mut transfer = handle.transfer(); - transfer.write_function(|data| { - buf.extend(data); - Ok(data.len()) - })?; - transfer.perform().unwrap(); - } - Ok(String::from_utf8(buf)?) - } - fn read_from_autoyast(&self) -> anyhow::Result { const TMP_DIR_PREFIX: &str = "autoyast"; const AUTOINST_JSON: &str = "autoinst.json"; From 6643bbe4a345021ff0cf444391ac85db7aa3cfff Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Thu, 30 May 2024 16:12:31 +0200 Subject: [PATCH 4/9] update documentation --- autoinstallation/README.md | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/autoinstallation/README.md b/autoinstallation/README.md index 5c6b325562..30b9216eb4 100644 --- a/autoinstallation/README.md +++ b/autoinstallation/README.md @@ -104,12 +104,12 @@ this scenario, it is expected to use the CLI to interact with Agama. In addition any other tool available in the installation media. What's more, when using the Live ISO, you could install your own tools. -Below there is a minimal working example to install ALP Dolomite: +Below there is a minimal working example to install Tumbleweed: ```sh set -ex -/usr/bin/agama config set software.product=ALP-Dolomite +/usr/bin/agama config set product.id=Tumbleweed /usr/bin/agama config set user.userName=joe user.password=doe /usr/bin/agama install ``` @@ -133,9 +133,9 @@ internal network. ```sh set -ex -/usr/bin/agama profile download ftp://my.server/tricky_hardware_setup.sh +/usr/bin/agama download ftp://my.server/tricky_hardware_setup.sh > tricky_hardware_setup.sh sh tricky_hardware_setup.sh -/usr/bin/agama config set software.product=Tumbleweed +/usr/bin/agama config set product.id=Tumbleweed /usr/bin/agama config set user.userName=joe user.password=doe /usr/bin/agama install ``` @@ -147,13 +147,11 @@ Jsonnet may be unable to handle all of the profile changes that users wish to ma ``` set -ex -/usr/bin/agama profile download ftp://my.server/profile.json +/usr/bin/agama download ftp://my.server/profile.json > /root/profile.json # modify profile.json here -/usr/bin/agama profile validate profile.json -/usr/bin/agama config load profile.json - +/usr/bin/agama profile import file:///root/profile.json /usr/bin/agama install ``` @@ -169,7 +167,7 @@ Agama and before installing RPMs, such as changing the fstab and mount an extra ```sh set -ex -/usr/bin/agama config set software.product=Tumbleweed +/usr/bin/agama config set product.id=Tumbleweed /usr/bin/agama config set user.userName=joe user.password=doe /usr/bin/agama install --until partitioning # install till the partitioning step @@ -191,9 +189,9 @@ software for internal network, then it must be modified before umount. ```sh set -ex -/usr/bin/agama profile download ftp://my.server/velociraptor.config +/usr/bin/agama download ftp://my.server/velociraptor.config -/usr/bin/agama config set software.product=Tumbleweed +/usr/bin/agama config set product.id=Tumbleweed /usr/bin/agama config set user.userName=joe user.password=doe /usr/bin/agama install --until deploy # do partitioning, rpm installation and configuration step @@ -218,7 +216,7 @@ some kernel tuning or adding some remote storage that needs to be mounted during ```sh set -ex -/usr/bin/agama config set software.product=Tumbleweed +/usr/bin/agama config set product.id=Tumbleweed /usr/bin/agama config set user.userName=joe user.password=doe /usr/bin/agama install --until deploy # do partitioning, rpm installation and configuration step From 3408a60464b4145e810124414e68859243db74f1 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 31 May 2024 07:27:10 +0200 Subject: [PATCH 5/9] improve help for config --- rust/agama-cli/src/config.rs | 7 ++++++- rust/agama-cli/src/profile.rs | 9 ++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/rust/agama-cli/src/config.rs b/rust/agama-cli/src/config.rs index 7b55dfa3a3..a2a65cb3c7 100644 --- a/rust/agama-cli/src/config.rs +++ b/rust/agama-cli/src/config.rs @@ -35,10 +35,15 @@ pub enum ConfigCommands { /// /// It is possible that many configuration settings do not have a value. Those settings /// are not included in the output. + /// + /// The output of command can be used as file content for `agama config load`. Show, /// Loads the configuration from a JSON file. - Load { path: String }, + Load { + /// Local path to file with configuration. For schema see /usr/share/agama-cli/profile.json.schema + path: String, + }, } pub enum ConfigAction { diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index d8775ed9f3..0a8513ad66 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -1,8 +1,7 @@ -use agama_lib::profile::{ProfileEvaluator, AutoyastProfile, ProfileValidator, ValidationResult}; +use agama_lib::profile::{AutoyastProfile, ProfileEvaluator, ProfileValidator, ValidationResult}; use anyhow::Context; use clap::Subcommand; use curl::easy::Easy; -use url::Url; use std::os::unix::process::CommandExt; use std::{ fs::File, @@ -11,6 +10,7 @@ use std::{ process::Command, }; use tempfile::TempDir; +use url::Url; #[derive(Subcommand, Debug)] pub enum ProfileCommands { @@ -38,7 +38,6 @@ pub enum ProfileCommands { }, } - pub fn download(url: &str, mut out_fd: impl Write) -> anyhow::Result<()> { let mut handle = Easy::new(); handle.url(url)?; @@ -101,7 +100,7 @@ async fn import(url_string: String, dir: Option) -> anyhow::Result<()> // just download profile download(&url_string, output_fd)?; } - + // exec shell scripts if output_file.ends_with(".sh") { let err = Command::new("bash") @@ -139,7 +138,7 @@ async fn import(url_string: String, dir: Option) -> anyhow::Result<()> Ok(()) } -fn autoyast(url_string: String) -> anyhow::Result<()>{ +fn autoyast(url_string: String) -> anyhow::Result<()> { let url = Url::parse(&url_string)?; let reader = AutoyastProfile::new(&url)?; reader.read(std::io::stdout())?; From adc04960c98cce07d72f64aecf8f616ce490d4a9 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Fri, 31 May 2024 08:19:55 +0200 Subject: [PATCH 6/9] improve documentation of profile subcommand --- rust/agama-cli/src/profile.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index 0a8513ad66..78d40ae88f 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -14,14 +14,29 @@ use url::Url; #[derive(Subcommand, Debug)] pub enum ProfileCommands { - /// Download the autoyast profile and convert it to json - Autoyast { url: String }, + /// Download the autoyast profile and print resulting json + Autoyast { + /// URL to autoyast XML, erb or rules&classes dir. Supports + /// all schemas that autoyast supports. + url: String, + }, /// Validate a profile using JSON Schema - Validate { path: String }, + /// + /// Schema is available at /usr/share/agama-cli/profile.schema.json + Validate { + /// Local path to json file + path: String, + }, /// Evaluate a profile, injecting the hardware information from D-Bus - Evaluate { path: String }, + /// + /// For example of jsonnet profile see + /// https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/examples/profile.jsonnet + Evaluate { + /// Path to jsonnet file. + path: String, + }, /// Process autoinstallation profile and loads it into agama /// From 3c7f4416064e6e8336df80e89c73a0f6863474cf Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 3 Jun 2024 09:47:33 +0200 Subject: [PATCH 7/9] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Imobach González Sosa --- rust/agama-cli/src/commands.rs | 6 +++--- rust/agama-cli/src/profile.rs | 12 ++++++------ rust/agama-lib/src/profile.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/rust/agama-cli/src/commands.rs b/rust/agama-cli/src/commands.rs index 954b3c484c..71c5df6a53 100644 --- a/rust/agama-cli/src/commands.rs +++ b/rust/agama-cli/src/commands.rs @@ -75,11 +75,11 @@ pub enum Commands { /// Download file from given URL /// - /// Purpose of this command is to allow download from all supported schemas. + /// The purpose of this command is to download files using AutoYaST supported schemas (e.g. device:// or relurl://). /// It can be used to download additional scripts, configuration files and so on. - /// For agama autoinstallation profiles it can be also used, but unless additional processing is required + /// You can use it for downloading Agama autoinstallation profiles. However, unless you need additional processing, /// the "agama profile import" is recommended. - /// For autoyast conversion use directly "agama profile autoyast". + /// If you want to convert an AutoYaST profile, use "agama profile autoyast". Download { /// URL pointing to file for download url: String, diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index 78d40ae88f..ba6a8728f6 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -16,7 +16,7 @@ use url::Url; pub enum ProfileCommands { /// Download the autoyast profile and print resulting json Autoyast { - /// URL to autoyast XML, erb or rules&classes dir. Supports + /// AutoYaST profile's URL. Any AutoYaST scheme, ERB and rules/classes are supported. /// all schemas that autoyast supports. url: String, }, @@ -31,7 +31,7 @@ pub enum ProfileCommands { /// Evaluate a profile, injecting the hardware information from D-Bus /// - /// For example of jsonnet profile see + /// For an example of Jsonnet-based profile, see /// https://github.com/openSUSE/agama/blob/master/rust/agama-lib/share/examples/profile.jsonnet Evaluate { /// Path to jsonnet file. @@ -44,11 +44,11 @@ pub enum ProfileCommands { /// installation. Unless there is a need to inject additional commands between processing /// use this command instead of set of underlying commands. Import { - /// URL where profile is located. Supported schemas are all that download supports and additionally - /// autoyast specific ones. Supported files are json, jsonnet, sh for agama profiles and erb, xml, directory - /// for autoyast support. + /// Profile's URL. Supports the same schemas than te "download" command plus + /// AutoYaST specific ones. Supported files are json, jsonnet, sh for Agama profiles and ERB, XML, and rules/classes directories + /// for AutoYaST support. url: String, - /// Specific directory where all processing happens. If not specific temporary directory is used + /// Specific directory where all processing happens. By default it uses a temporary directory dir: Option, }, } diff --git a/rust/agama-lib/src/profile.rs b/rust/agama-lib/src/profile.rs index 4013f10f29..f6e7555132 100644 --- a/rust/agama-lib/src/profile.rs +++ b/rust/agama-lib/src/profile.rs @@ -24,7 +24,7 @@ impl AutoyastProfile { out_fd.write_all(content.as_bytes())?; Ok(()) } else { - let msg = format!("Unsupported autoyast format at {}", self.url); + let msg = format!("Unsupported AutoYaST format at {}", self.url); Err(anyhow::Error::msg(msg)) } } From 1fa8b363e44394708a11b2fe200952ac6bdfb833 Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 3 Jun 2024 09:50:52 +0200 Subject: [PATCH 8/9] changes --- rust/package/agama.changes | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/rust/package/agama.changes b/rust/package/agama.changes index 05ab01c630..d8b8d4e709 100644 --- a/rust/package/agama.changes +++ b/rust/package/agama.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Mon Jun 3 07:49:16 UTC 2024 - Josef Reidinger + +- CLI: Add new commands "agama download" and + "agama profile autoyast" and remove "agama profile download" to + separate common curl-like download and autoyast specific one + which do conversion to json (gh#openSUSE/agama#1279) + ------------------------------------------------------------------- Wed May 29 12:15:37 UTC 2024 - Josef Reidinger From 88816125254b818fa8878a00af5be4733345b0ee Mon Sep 17 00:00:00 2001 From: Josef Reidinger Date: Mon, 3 Jun 2024 09:52:09 +0200 Subject: [PATCH 9/9] rename read to read_into to better reflect output parameter --- rust/agama-cli/src/profile.rs | 4 ++-- rust/agama-lib/src/profile.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rust/agama-cli/src/profile.rs b/rust/agama-cli/src/profile.rs index ba6a8728f6..c60101e949 100644 --- a/rust/agama-cli/src/profile.rs +++ b/rust/agama-cli/src/profile.rs @@ -110,7 +110,7 @@ async fn import(url_string: String, dir: Option) -> anyhow::Result<()> let output_fd = File::create(output_path.clone())?; if path.ends_with(".xml") || path.ends_with(".erb") || path.ends_with('/') { // autoyast specific download and convert to json - AutoyastProfile::new(&url)?.read(output_fd)?; + AutoyastProfile::new(&url)?.read_into(output_fd)?; } else { // just download profile download(&url_string, output_fd)?; @@ -156,7 +156,7 @@ async fn import(url_string: String, dir: Option) -> anyhow::Result<()> fn autoyast(url_string: String) -> anyhow::Result<()> { let url = Url::parse(&url_string)?; let reader = AutoyastProfile::new(&url)?; - reader.read(std::io::stdout())?; + reader.read_into(std::io::stdout())?; Ok(()) } diff --git a/rust/agama-lib/src/profile.rs b/rust/agama-lib/src/profile.rs index f6e7555132..c4f54d27e1 100644 --- a/rust/agama-lib/src/profile.rs +++ b/rust/agama-lib/src/profile.rs @@ -17,7 +17,7 @@ impl AutoyastProfile { Ok(Self { url: url.clone() }) } - pub fn read(&self, mut out_fd: impl Write) -> anyhow::Result<()> { + pub fn read_into(&self, mut out_fd: impl Write) -> anyhow::Result<()> { let path = self.url.path(); if path.ends_with(".xml") || path.ends_with(".erb") || path.ends_with('/') { let content = self.read_from_autoyast()?;