From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 2DDCF9699 for ; Tue, 26 Apr 2022 12:14:36 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 24BDA19EA3 for ; Tue, 26 Apr 2022 12:14:06 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id AF51C19E7B for ; Tue, 26 Apr 2022 12:14:03 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 80E8342B98 for ; Tue, 26 Apr 2022 12:14:03 +0200 (CEST) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Tue, 26 Apr 2022 12:13:58 +0200 Message-Id: <20220426101401.3216096-6-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220426101401.3216096-1-d.csapak@proxmox.com> References: <20220426101401.3216096-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.127 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [main.rs] Subject: [pve-devel] [PATCH proxmox-backup v2 5/5] file-restore: add 'timeout' and 'json-error' parameter X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Apr 2022 10:14:36 -0000 timeout limits the code with the given timeout in seconds, and 'json-error' return json to stdout when the call returns an error like this: { "msg": "error message", "error": true, "code": , // if it was an http error } with both options set, a client can more easily determine if the call ran into a timeout (since it will return a 503 error), and can poll it again both is done behind new parameters, so that we can stay backwards-compatible Signed-off-by: Dominik Csapak --- proxmox-file-restore/src/main.rs | 62 ++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/proxmox-file-restore/src/main.rs b/proxmox-file-restore/src/main.rs index 4b327f6b..6b5e65b9 100644 --- a/proxmox-file-restore/src/main.rs +++ b/proxmox-file-restore/src/main.rs @@ -11,6 +11,7 @@ use proxmox_router::cli::{ get_output_format, run_cli_command, CliCommand, CliCommandMap, CliEnvironment, ColumnConfig, OUTPUT_FORMAT, }; +use proxmox_router::{http_err, HttpError}; use proxmox_schema::api; use proxmox_sys::fs::{create_path, CreateOptions}; use pxar::accessor::aio::Accessor; @@ -211,6 +212,18 @@ async fn list_files( schema: OUTPUT_FORMAT, optional: true, }, + "json-error": { + type: Boolean, + description: "If set, errors are returned as json instead of writing to stderr", + optional: true, + default: false, + }, + "timeout": { + type: Integer, + description: "Defines the maximum time the call can should take.", + minimum: 1, + optional: true, + }, } }, returns: { @@ -222,7 +235,14 @@ async fn list_files( } )] /// List a directory from a backup snapshot. -async fn list(snapshot: String, path: String, base64: bool, param: Value) -> Result<(), Error> { +async fn list( + snapshot: String, + path: String, + base64: bool, + json_error: bool, + timeout: Option, + param: Value, +) -> Result<(), Error> { let repo = extract_repository_from_value(¶m)?; let snapshot: BackupDir = snapshot.parse()?; let path = parse_path(path, base64)?; @@ -246,7 +266,43 @@ async fn list(snapshot: String, path: String, base64: bool, param: Value) -> Res None => None, }; - let result = list_files(repo, snapshot, path, crypt_config, keyfile, driver).await?; + let result = if let Some(timeout) = timeout { + match tokio::time::timeout( + std::time::Duration::from_secs(timeout), + list_files(repo, snapshot, path, crypt_config, keyfile, driver), + ) + .await + { + Ok(res) => res, + Err(_) => Err(http_err!(SERVICE_UNAVAILABLE, "list not finished in time")), + } + } else { + list_files(repo, snapshot, path, crypt_config, keyfile, driver).await + }; + + let output_format = get_output_format(¶m); + + if let Err(err) = result { + if !json_error { + return Err(err); + } + let (msg, code) = match err.downcast_ref::() { + Some(HttpError { code, message }) => (message.clone(), Some(code)), + None => (err.to_string(), None), + }; + let mut json_err = json!({ + "error": true, + "message": msg, + }); + if let Some(code) = code { + json_err["code"] = Value::from(code.as_u16()); + } + match output_format.as_ref() { + "json-pretty" => println!("{}", serde_json::to_string_pretty(&json_err)?), + _ => println!("{}", serde_json::to_string(&json_err)?), + } + return Ok(()); + } let options = default_table_format_options() .sortby("type", false) @@ -258,7 +314,7 @@ async fn list(snapshot: String, path: String, base64: bool, param: Value) -> Res let output_format = get_output_format(¶m); format_and_print_result_full( - &mut json!(result), + &mut json!(result.unwrap()), &API_METHOD_LIST.returns, &output_format, &options, -- 2.30.2