* [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group
@ 2023-09-08 11:44 Gabriel Goller
2023-09-08 11:44 ` [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper Gabriel Goller
2023-12-07 12:51 ` [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
0 siblings, 2 replies; 6+ messages in thread
From: Gabriel Goller @ 2023-09-08 11:44 UTC (permalink / raw)
To: pbs-devel
Added the command `proxmox-backup-client group forget <group>` so
that we can forget (delete) whole groups with all the containing
snapshots. As this is quite dangerous, we added a prompt, so the
user has to confirm the operation.
Fixed paths for local dependencies in Cargo.toml.
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
proxmox-backup-client/src/group.rs | 66 ++++++++++++++++++++++++++++++
proxmox-backup-client/src/main.rs | 3 ++
2 files changed, 69 insertions(+)
create mode 100644 proxmox-backup-client/src/group.rs
diff --git a/proxmox-backup-client/src/group.rs b/proxmox-backup-client/src/group.rs
new file mode 100644
index 00000000..93b97a59
--- /dev/null
+++ b/proxmox-backup-client/src/group.rs
@@ -0,0 +1,66 @@
+use anyhow::Error;
+use serde_json::Value;
+
+use proxmox_router::cli::{ask_for_confirmation, CliCommand, CliCommandMap};
+use proxmox_schema::api;
+
+use pbs_api_types::{BackupGroup, BackupNamespace};
+use pbs_client::tools::{connect, extract_repository_from_value};
+use crate::{
+ complete_backup_group, complete_namespace, complete_repository, merge_group_into,
+ REPO_URL_SCHEMA,
+};
+
+pub fn group_mgmt_cli() -> CliCommandMap {
+ CliCommandMap::new().insert(
+ "forget",
+ CliCommand::new(&API_METHOD_FORGET_GROUP)
+ .arg_param(&["group"])
+ .completion_cb("ns", complete_namespace)
+ .completion_cb("repository", complete_repository)
+ .completion_cb("group", complete_backup_group),
+ )
+}
+
+#[api(
+ input: {
+ properties: {
+ group: {
+ type: String,
+ description: "Backup group",
+ },
+ repository: {
+ schema: REPO_URL_SCHEMA,
+ optional: true,
+ },
+ ns: {
+ type: BackupNamespace,
+ optional: true,
+ },
+ }
+ }
+)]
+/// Forget (remove) backup snapshots.
+async fn forget_group(group: String, param: Value) -> Result<Value, Error> {
+ let backup_group: BackupGroup = group.parse()?;
+ let repo = extract_repository_from_value(¶m)?;
+ let client = connect(&repo)?;
+
+ let mut api_params = param;
+ merge_group_into(api_params.as_object_mut().unwrap(), backup_group.clone());
+
+ let path = format!("api2/json/admin/datastore/{}/snapshots", repo.store());
+ let result = client.get(&path, Some(api_params.clone())).await?;
+ let snapshots = result["data"].as_array().unwrap().len();
+
+ ask_for_confirmation(format!(
+ "Delete group \"{}\" with {} snapshot(s)?",
+ backup_group, snapshots
+ ))?;
+
+ let path = format!("api2/json/admin/datastore/{}/groups", repo.store());
+ let _ = client.delete(&path, Some(api_params)).await?;
+
+ println!("Successfully deleted group!");
+ Ok(Value::Null)
+}
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index 1a13291a..975682de 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -72,6 +72,8 @@ mod catalog;
pub use catalog::*;
mod snapshot;
pub use snapshot::*;
+mod group;
+pub use group::*;
pub mod key;
pub mod namespace;
@@ -1783,6 +1785,7 @@ fn main() {
.insert("benchmark", benchmark_cmd_def)
.insert("change-owner", change_owner_cmd_def)
.insert("namespace", namespace::cli_map())
+ .insert("group", group_mgmt_cli())
.alias(&["files"], &["snapshot", "files"])
.alias(&["forget"], &["snapshot", "forget"])
.alias(&["upload-log"], &["snapshot", "upload-log"])
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper
2023-09-08 11:44 [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
@ 2023-09-08 11:44 ` Gabriel Goller
2023-09-27 10:13 ` Wolfgang Bumiller
2023-12-07 12:51 ` [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
1 sibling, 1 reply; 6+ messages in thread
From: Gabriel Goller @ 2023-09-08 11:44 UTC (permalink / raw)
To: pbs-devel
Added `ask_for_confirmation` helper that outputs a prompt and
lets the user confirm or deny it. Also added localization using
`libc::nl_langinfo()` to match/show a `yes` or `no` in the correct
language.
Implemented to close #4763.
Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
---
update v3:
- added localization using `libc::nl_langinfo`
note: skipped to version 3, so that the whole patch series has
the same version number.
proxmox-router/Cargo.toml | 1 +
proxmox-router/src/cli/mod.rs | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/proxmox-router/Cargo.toml b/proxmox-router/Cargo.toml
index 1c08ce2..e0d67d0 100644
--- a/proxmox-router/Cargo.toml
+++ b/proxmox-router/Cargo.toml
@@ -19,6 +19,7 @@ percent-encoding.workspace = true
serde_json.workspace = true
serde.workspace = true
unicode-width ="0.1.8"
+regex.workspace = true
# cli:
tokio = { workspace = true, features = [], optional = true }
diff --git a/proxmox-router/src/cli/mod.rs b/proxmox-router/src/cli/mod.rs
index 208df4a..1dcfaf0 100644
--- a/proxmox-router/src/cli/mod.rs
+++ b/proxmox-router/src/cli/mod.rs
@@ -12,7 +12,10 @@
//! - Ability to create interactive commands (using ``rustyline``)
//! - Supports complex/nested commands
-use std::collections::HashMap;
+use std::{
+ collections::HashMap,
+ io::{self, Write},
+};
use crate::ApiMethod;
@@ -62,6 +65,35 @@ pub fn init_cli_logger(env_var_name: &str, default_log_level: &str) {
.init();
}
+pub fn ask_for_confirmation(query: String) -> Result<(), io::Error> {
+ use std::ffi::CStr;
+ let yes_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::YESEXPR)) }
+ .to_str()
+ .unwrap_or("^[yY]$");
+ let no_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::NOEXPR)) }
+ .to_str()
+ .unwrap_or("^[nN]$");
+
+ let n = no_expr.chars().find(|c| c.is_uppercase()).unwrap_or('N');
+ let y = yes_expr.chars().find(|c| c.is_uppercase()).unwrap_or('Y');
+ print!("{query} [{y}/{n}]: ");
+
+ use regex::Regex;
+ // .unwrap() is okay, because we should always get a correct regex (see `.unwrap_or()` calls above)
+ let yes_regex: Regex = Regex::new(yes_expr).unwrap();
+
+ io::stdout().flush()?;
+ let stdin = io::stdin();
+ let mut line = String::new();
+ stdin.read_line(&mut line)?;
+
+ if yes_regex.is_match(line.trim()) {
+ Ok(())
+ } else {
+ Err(io::Error::new(io::ErrorKind::Other, "Aborted"))
+ }
+}
+
/// Define a simple CLI command.
pub struct CliCommand {
/// The Schema definition.
--
2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper
2023-09-08 11:44 ` [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper Gabriel Goller
@ 2023-09-27 10:13 ` Wolfgang Bumiller
2023-09-27 10:48 ` Fabian Grünbichler
0 siblings, 1 reply; 6+ messages in thread
From: Wolfgang Bumiller @ 2023-09-27 10:13 UTC (permalink / raw)
To: Gabriel Goller; +Cc: pbs-devel
On Fri, Sep 08, 2023 at 01:44:09PM +0200, Gabriel Goller wrote:
> Added `ask_for_confirmation` helper that outputs a prompt and
> lets the user confirm or deny it. Also added localization using
> `libc::nl_langinfo()` to match/show a `yes` or `no` in the correct
> language.
> Implemented to close #4763.
>
> Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
> ---
>
> update v3:
> - added localization using `libc::nl_langinfo`
>
> note: skipped to version 3, so that the whole patch series has
> the same version number.
>
> proxmox-router/Cargo.toml | 1 +
> proxmox-router/src/cli/mod.rs | 34 +++++++++++++++++++++++++++++++++-
> 2 files changed, 34 insertions(+), 1 deletion(-)
>
> diff --git a/proxmox-router/Cargo.toml b/proxmox-router/Cargo.toml
> index 1c08ce2..e0d67d0 100644
> --- a/proxmox-router/Cargo.toml
> +++ b/proxmox-router/Cargo.toml
> @@ -19,6 +19,7 @@ percent-encoding.workspace = true
> serde_json.workspace = true
> serde.workspace = true
> unicode-width ="0.1.8"
> +regex.workspace = true
>
> # cli:
> tokio = { workspace = true, features = [], optional = true }
> diff --git a/proxmox-router/src/cli/mod.rs b/proxmox-router/src/cli/mod.rs
> index 208df4a..1dcfaf0 100644
> --- a/proxmox-router/src/cli/mod.rs
> +++ b/proxmox-router/src/cli/mod.rs
> @@ -12,7 +12,10 @@
> //! - Ability to create interactive commands (using ``rustyline``)
> //! - Supports complex/nested commands
>
> -use std::collections::HashMap;
> +use std::{
> + collections::HashMap,
> + io::{self, Write},
> +};
>
> use crate::ApiMethod;
>
> @@ -62,6 +65,35 @@ pub fn init_cli_logger(env_var_name: &str, default_log_level: &str) {
> .init();
> }
>
> +pub fn ask_for_confirmation(query: String) -> Result<(), io::Error> {
IMO a generic helper should take the default as parameter (to decide on
the upper/lower-casing, see below), and also return a boolean for the
result. The Err case should be exclusively for actual errors (from
`.read_line()`).
> + use std::ffi::CStr;
> + let yes_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::YESEXPR)) }
> + .to_str()
> + .unwrap_or("^[yY]$");
> + let no_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::NOEXPR)) }
> + .to_str()
> + .unwrap_or("^[nN]$");
> +
> + let n = no_expr.chars().find(|c| c.is_uppercase()).unwrap_or('N');
> + let y = yes_expr.chars().find(|c| c.is_uppercase()).unwrap_or('Y');
> + print!("{query} [{y}/{n}]: ");
Usually, the uppercase letter is used for the default for when typing
nothing, while the other one is lowercase.
Now I was also wondering what we should do if no upper/lowercase letter
exists, but then again, it seems yY and nN are pretty much always
included. I checked at least de_DE, ja_JP and zh_CN next to en_US, and
I'm fairly certain we can rely on that, since I'm assuming this is
exactly what `rpmatch(3)` does, which explicitly states that `y` and `n`
work regardless of locale.
> +
> + use regex::Regex;
> + // .unwrap() is okay, because we should always get a correct regex (see `.unwrap_or()` calls above)
> + let yes_regex: Regex = Regex::new(yes_expr).unwrap();
It might be worth caching this in a static `OnceCell`.
> +
> + io::stdout().flush()?;
> + let stdin = io::stdin();
> + let mut line = String::new();
> + stdin.read_line(&mut line)?;
> +
> + if yes_regex.is_match(line.trim()) {
> + Ok(())
> + } else {
> + Err(io::Error::new(io::ErrorKind::Other, "Aborted"))
> + }
> +}
> +
> /// Define a simple CLI command.
> pub struct CliCommand {
> /// The Schema definition.
> --
> 2.39.2
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper
2023-09-27 10:13 ` Wolfgang Bumiller
@ 2023-09-27 10:48 ` Fabian Grünbichler
2023-09-27 14:45 ` Gabriel Goller
0 siblings, 1 reply; 6+ messages in thread
From: Fabian Grünbichler @ 2023-09-27 10:48 UTC (permalink / raw)
To: Gabriel Goller, Proxmox Backup Server development discussion
On September 27, 2023 12:13 pm, Wolfgang Bumiller wrote:
> On Fri, Sep 08, 2023 at 01:44:09PM +0200, Gabriel Goller wrote:
>> Added `ask_for_confirmation` helper that outputs a prompt and
>> lets the user confirm or deny it. Also added localization using
>> `libc::nl_langinfo()` to match/show a `yes` or `no` in the correct
>> language.
>> Implemented to close #4763.
>>
>> Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
>> ---
>>
>> update v3:
>> - added localization using `libc::nl_langinfo`
>>
>> note: skipped to version 3, so that the whole patch series has
>> the same version number.
>>
> [..]
>> + use std::ffi::CStr;
>> + let yes_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::YESEXPR)) }
>> + .to_str()
>> + .unwrap_or("^[yY]$");
>> + let no_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::NOEXPR)) }
>> + .to_str()
>> + .unwrap_or("^[nN]$");
>> +
>> + let n = no_expr.chars().find(|c| c.is_uppercase()).unwrap_or('N');
>> + let y = yes_expr.chars().find(|c| c.is_uppercase()).unwrap_or('Y');
>> + print!("{query} [{y}/{n}]: ");
>
> Usually, the uppercase letter is used for the default for when typing
> nothing, while the other one is lowercase.
>
> Now I was also wondering what we should do if no upper/lowercase letter
> exists, but then again, it seems yY and nN are pretty much always
> included. I checked at least de_DE, ja_JP and zh_CN next to en_US, and
> I'm fairly certain we can rely on that, since I'm assuming this is
> exactly what `rpmatch(3)` does, which explicitly states that `y` and `n`
> work regardless of locale.
there definitely are locales that either don't include 'y' and/or 'n',
or do so in a misleading manner.
one example:
$ LC_MESSAGES=sw_KE.UTF-8 locale yesexpr
^[+1nNyY]
$ LC_MESSAGES=sw_KE.UTF-8 locale noexpr
^[-0hHlL]
this is also the case for nl_langinfo, at least if the code in question
actually calls setlocale/uselocale at some point, which we don't do I
think?
in any case, I am not sure whether localizing just the prompt answers
makes much sense, if we don't localize log messages/CLI output/.. in
general?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper
2023-09-27 10:48 ` Fabian Grünbichler
@ 2023-09-27 14:45 ` Gabriel Goller
0 siblings, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2023-09-27 14:45 UTC (permalink / raw)
To: Fabian Grünbichler, Proxmox Backup Server development discussion
On 9/27/23 12:48, Fabian Grünbichler wrote:
> On September 27, 2023 12:13 pm, Wolfgang Bumiller wrote:
>> On Fri, Sep 08, 2023 at 01:44:09PM +0200, Gabriel Goller wrote:
>>> Added `ask_for_confirmation` helper that outputs a prompt and
>>> lets the user confirm or deny it. Also added localization using
>>> `libc::nl_langinfo()` to match/show a `yes` or `no` in the correct
>>> language.
>>> Implemented to close #4763.
>>>
>>> Signed-off-by: Gabriel Goller <g.goller@proxmox.com>
>>> ---
>>>
>>> update v3:
>>> - added localization using `libc::nl_langinfo`
>>>
>>> note: skipped to version 3, so that the whole patch series has
>>> the same version number.
>>>
>> [..]
>>> + use std::ffi::CStr;
>>> + let yes_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::YESEXPR)) }
>>> + .to_str()
>>> + .unwrap_or("^[yY]$");
>>> + let no_expr = unsafe { CStr::from_ptr(libc::nl_langinfo(libc::NOEXPR)) }
>>> + .to_str()
>>> + .unwrap_or("^[nN]$");
>>> +
>>> + let n = no_expr.chars().find(|c| c.is_uppercase()).unwrap_or('N');
>>> + let y = yes_expr.chars().find(|c| c.is_uppercase()).unwrap_or('Y');
>>> + print!("{query} [{y}/{n}]: ");
>> Usually, the uppercase letter is used for the default for when typing
>> nothing, while the other one is lowercase.
>>
>> Now I was also wondering what we should do if no upper/lowercase letter
>> exists, but then again, it seems yY and nN are pretty much always
>> included. I checked at least de_DE, ja_JP and zh_CN next to en_US, and
>> I'm fairly certain we can rely on that, since I'm assuming this is
>> exactly what `rpmatch(3)` does, which explicitly states that `y` and `n`
>> work regardless of locale.
> there definitely are locales that either don't include 'y' and/or 'n',
> or do so in a misleading manner.
>
> one example:
>
> $ LC_MESSAGES=sw_KE.UTF-8 locale yesexpr
> ^[+1nNyY]
>
> $ LC_MESSAGES=sw_KE.UTF-8 locale noexpr
> ^[-0hHlL]
>
> this is also the case for nl_langinfo, at least if the code in question
> actually calls setlocale/uselocale at some point, which we don't do I
> think?
oh, yeah right, we never called it. I can add this lines before using
`nl_langinfo`:
```
unsafe { libc::setlocale(libc::LC_ALL, empty_cstring.as_ptr()) };
```
this uses the environment locale on the system [0].
> in any case, I am not sure whether localizing just the prompt answers
> makes much sense, if we don't localize log messages/CLI output/.. in
> general?
Hmm, it *could* be useful for inputs though, especially those that
need to be matched. Think of keyboards in different languages.
[0]:
https://www.gnu.org/software/libc/manual/html_node/Setting-the-Locale.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group
2023-09-08 11:44 [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
2023-09-08 11:44 ` [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper Gabriel Goller
@ 2023-12-07 12:51 ` Gabriel Goller
1 sibling, 0 replies; 6+ messages in thread
From: Gabriel Goller @ 2023-12-07 12:51 UTC (permalink / raw)
To: pbs-devel
Submitted a new patch!
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-12-07 12:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-08 11:44 [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
2023-09-08 11:44 ` [pbs-devel] [PATCH proxmox v3] router: cli: added `ask_for_confirmation` helper Gabriel Goller
2023-09-27 10:13 ` Wolfgang Bumiller
2023-09-27 10:48 ` Fabian Grünbichler
2023-09-27 14:45 ` Gabriel Goller
2023-12-07 12:51 ` [pbs-devel] [PATCH proxmox-backup v3] close #4763: client: added command to forget backup group Gabriel Goller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal