Skip to content

Commit

Permalink
Merge pull request #668 from openSUSE/cli_auto_questions
Browse files Browse the repository at this point in the history
CLI automatic answers to questions
  • Loading branch information
jreidinger authored Jul 18, 2023
2 parents bd024b8 + ef7ca5e commit 410c673
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 15 deletions.
9 changes: 7 additions & 2 deletions doc/cli_guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ There are pending questions. Please, answer questions first: agama questions.

## Non Interactive Mode

Commands should offer a `--non-interactive` option to make scripting possible. The non interactive mode should allow answering questions automatically.
There is a `questions` subcommand that support `mode` and `answers` subcommands.
The `mode` subcommand allows to set `interactive` and `non-interactive` modes.
The `answers` allows to pass a file with predefined answers.

TBD: Non interactive mode will be defined later in the next iteration.
~~~
agama questions mode non-interactive
agama questions answers /tmp/answers.json
~~~
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/agama-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ thiserror = "1.0.39"
convert_case = "0.6.0"
console = "0.15.7"
anyhow = "1.0.71"
log = "0.4"

[[bin]]
name = "agama"
Expand Down
4 changes: 4 additions & 0 deletions rust/agama-cli/src/commands.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::config::ConfigCommands;
use crate::profile::ProfileCommands;
use crate::questions::QuestionsCommands;
use clap::Subcommand;

#[derive(Subcommand, Debug)]
Expand All @@ -20,4 +21,7 @@ pub enum Commands {
/// Autoinstallation profile handling
#[command(subcommand)]
Profile(ProfileCommands),
/// Questions handling
#[command(subcommand)]
Questions(QuestionsCommands),
}
3 changes: 3 additions & 0 deletions rust/agama-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod error;
mod printers;
mod profile;
mod progress;
mod questions;

use crate::error::CliError;
use agama_lib::error::ServiceError;
Expand All @@ -17,6 +18,7 @@ use config::run as run_config_cmd;
use printers::Format;
use profile::run as run_profile_cmd;
use progress::InstallerProgress;
use questions::run as run_questions_cmd;
use std::{
process::{ExitCode, Termination},
thread::sleep,
Expand Down Expand Up @@ -128,6 +130,7 @@ async fn run_command(cli: Cli) -> anyhow::Result<()> {
let manager = build_manager().await?;
block_on(install(&manager, 3))
}
Commands::Questions(subcommand) => block_on(run_questions_cmd(subcommand)),
_ => unimplemented!(),
}
}
Expand Down
48 changes: 48 additions & 0 deletions rust/agama-cli/src/questions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use agama_lib::connection;
use agama_lib::proxies::Questions1Proxy;
use anyhow::{Context, Ok};
use clap::{Args, Subcommand, ValueEnum};

#[derive(Subcommand, Debug)]
pub enum QuestionsCommands {
/// Set mode for answering questions.
Mode(ModesArgs),
}

#[derive(Args, Debug)]
pub struct ModesArgs {
#[arg(value_enum)]
value: Modes,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum Modes {
Interactive,
NonInteractive,
}
// TODO when more commands is added, refactor and add it to agama-lib and share a bit of functionality
async fn set_mode(value: Modes) -> anyhow::Result<()> {
match value {
Modes::NonInteractive => {
let connection = connection().await?;
let proxy = Questions1Proxy::new(&connection)
.await
.context("Failed to connect to Questions service")?;

// TODO: how to print dbus error in that anyhow?
proxy
.use_default_answer()
.await
.context("Failed to set default answer")?;
}
Modes::Interactive => log::info!("not implemented"), //TODO do it
}

Ok(())
}

pub async fn run(subcommand: QuestionsCommands) -> anyhow::Result<()> {
match subcommand {
QuestionsCommands::Mode(value) => set_mode(value.value).await,
}
}
28 changes: 15 additions & 13 deletions rust/agama-lib/src/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,32 @@ trait Locale1 {
fn set_vconsole_keyboard(&self, value: &str) -> zbus::Result<()>;
}

#[dbus_proxy(
interface = "org.opensuse.Agama.Questions1",
default_service = "org.opensuse.Agama.Questions1",
default_path = "/org/opensuse/Agama/Questions1"
)]
#[dbus_proxy(interface = "org.opensuse.Agama.Questions1", assume_defaults = true)]
trait Questions1 {
/// Delete method
fn delete(&self, question: &zbus::zvariant::ObjectPath<'_>) -> zbus::Result<()>;

/// New method
#[dbus_proxy(name = "New")]
fn create(
fn new_generic(
&self,
class: &str,
text: &str,
options: &[&str],
default_option: &[&str],
default_option: &str,
data: std::collections::HashMap<&str, &str>,
) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;

/// NewLuksActivation method
fn new_luks_activation(
/// NewWithPassword method
fn new_with_password(
&self,
device: &str,
label: &str,
size: &str,
attempt: u8,
class: &str,
text: &str,
options: &[&str],
default_option: &str,
data: std::collections::HashMap<&str, &str>,
) -> zbus::Result<zbus::zvariant::OwnedObjectPath>;

/// UseDefaultAnswer method
fn use_default_answer(&self) -> zbus::Result<()>;
}
18 changes: 18 additions & 0 deletions rust/agama-lib/src/questions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ impl GenericQuestion {
}
}

/// Gets object path of given question. It is useful as parameter
/// for deleting it.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use agama_lib::questions::GenericQuestion;
/// let question = GenericQuestion::new(
/// 2,
/// "test_class".to_string(),
/// "Really?".to_string(),
/// vec!["Yes".to_string(), "No".to_string()],
/// "No".to_string(),
/// HashMap::new()
/// );
/// assert_eq!(question.object_path(), "/org/opensuse/Agama/Questions1/2".to_string());
/// ```
pub fn object_path(&self) -> String {
format!("/org/opensuse/Agama/Questions1/{}", self.id)
}
Expand Down
6 changes: 6 additions & 0 deletions rust/package/agama-cli.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Tue Jul 18 13:32:04 UTC 2023 - Josef Reidinger <[email protected]>

- Add to CLI "questions" subcommand with mode option to set
interactive and non-interactive mode (gh#openSUSE/agama#668)

-------------------------------------------------------------------
Mon Jul 17 13:36:56 UTC 2023 - Imobach Gonzalez Sosa <[email protected]>

Expand Down

0 comments on commit 410c673

Please sign in to comment.