From: Stefan Sterz <s.sterz@proxmox.com>
To: pbs-devel@lists.proxmox.com, pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH proxmox-backup v3 1/6] fix #3067: api: add support for multi-line comments in node.cfg
Date: Fri, 4 Mar 2022 12:31:57 +0100 [thread overview]
Message-ID: <20220304113202.4137916-2-s.sterz@proxmox.com> (raw)
In-Reply-To: <20220304113202.4137916-1-s.sterz@proxmox.com>
add support for multi-line comments to node.cfg and the api, similar to
how pve handles multi-line comments
Signed-off-by: Stefan Sterz <s.sterz@proxmox.com>
---
pbs-api-types/src/lib.rs | 9 +++++++
src/api2/node/config.rs | 4 +++
src/config/node.rs | 14 +++++++++-
src/tools/config.rs | 56 ++++++++++++++++++++++++++++++++++++++--
4 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs
index 754e7b22..3b1fad2c 100644
--- a/pbs-api-types/src/lib.rs
+++ b/pbs-api-types/src/lib.rs
@@ -137,6 +137,8 @@ const_regex! {
pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
+ pub MULTI_LINE_COMMENT_REGEX = r"(?m)^([[:^cntrl:]]*)$";
+
pub BACKUP_REPO_URL_REGEX = concat!(
r"^^(?:(?:(",
USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(),
@@ -273,6 +275,13 @@ pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (singl
.format(&SINGLE_LINE_COMMENT_FORMAT)
.schema();
+pub const MULTI_LINE_COMMENT_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&MULTI_LINE_COMMENT_REGEX);
+
+pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multiple lines).")
+ .format(&MULTI_LINE_COMMENT_FORMAT)
+ .schema();
+
pub const SUBSCRIPTION_KEY_SCHEMA: Schema = StringSchema::new("Proxmox Backup Server subscription key.")
.format(&SUBSCRIPTION_KEY_FORMAT)
.min_length(15)
diff --git a/src/api2/node/config.rs b/src/api2/node/config.rs
index 0a119354..3b267adc 100644
--- a/src/api2/node/config.rs
+++ b/src/api2/node/config.rs
@@ -64,6 +64,8 @@ pub enum DeletableProperty {
ciphers_tls_1_2,
/// Delete the default-lang property.
default_lang,
+ /// Delete any description
+ description,
}
#[api(
@@ -124,6 +126,7 @@ pub fn update_node_config(
DeletableProperty::ciphers_tls_1_3 => { config.ciphers_tls_1_3 = None; },
DeletableProperty::ciphers_tls_1_2 => { config.ciphers_tls_1_2 = None; },
DeletableProperty::default_lang => { config.default_lang = None; },
+ DeletableProperty::description => { config.description = None; },
}
}
}
@@ -139,6 +142,7 @@ pub fn update_node_config(
if update.ciphers_tls_1_3.is_some() { config.ciphers_tls_1_3 = update.ciphers_tls_1_3; }
if update.ciphers_tls_1_2.is_some() { config.ciphers_tls_1_2 = update.ciphers_tls_1_2; }
if update.default_lang.is_some() { config.default_lang = update.default_lang; }
+ if update.description.is_some() { config.description = update.description; }
crate::config::node::save_config(&config)?;
diff --git a/src/config/node.rs b/src/config/node.rs
index 0ba87450..ac6774e3 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -8,7 +8,11 @@ use proxmox_schema::{api, ApiStringFormat, ApiType, Updater};
use proxmox_http::ProxyConfig;
-use pbs_api_types::{EMAIL_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA, OPENSSL_CIPHERS_TLS_1_3_SCHEMA};
+use pbs_api_types::{
+ EMAIL_SCHEMA, MULTI_LINE_COMMENT_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
+ OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
+};
+
use pbs_buildcfg::configdir;
use pbs_config::{open_backup_lockfile, BackupLockGuard};
@@ -167,6 +171,10 @@ pub enum Translation {
"default-lang" : {
schema: Translation::API_SCHEMA,
optional: true,
+ },
+ "description" : {
+ optional: true,
+ schema: MULTI_LINE_COMMENT_SCHEMA,
}
},
)]
@@ -210,6 +218,10 @@ pub struct NodeConfig {
/// Default language used in the GUI
#[serde(skip_serializing_if = "Option::is_none")]
pub default_lang: Option<String>,
+
+ /// Node description
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub description: Option<String>,
}
impl NodeConfig {
diff --git a/src/tools/config.rs b/src/tools/config.rs
index f666a8ab..cc722094 100644
--- a/src/tools/config.rs
+++ b/src/tools/config.rs
@@ -31,8 +31,19 @@ pub fn value_from_str(input: &str, schema: &'static Schema) -> Result<Value, Err
let schema = object_schema(schema)?;
let mut config = Object::new();
+ let mut lines = input.lines().enumerate().peekable();
+ let mut description = String::new();
- for (lineno, line) in input.lines().enumerate() {
+ while let Some((_, line)) = lines.next_if(|(_, line)| line.starts_with('#')) {
+ description.push_str(&line[1..]);
+ description.push('\n');
+ }
+
+ if !description.is_empty() {
+ config.insert("description".to_string(), Value::String(description));
+ }
+
+ for (lineno, line) in lines {
let line = line.trim();
if line.starts_with('#') || line.is_empty() {
continue;
@@ -133,9 +144,17 @@ pub fn value_to_bytes(value: &Value, schema: &'static Schema) -> Result<Vec<u8>,
/// Note: the object must have already been verified at this point.
fn object_to_writer(output: &mut dyn Write, object: &Object) -> Result<(), Error> {
+ // special key `description` for multi-line notes, must be written before everything else
+ if let Some(Value::String(description)) = object.get("description") {
+ for lines in description.lines() {
+ writeln!(output, "#{}", lines)?;
+ }
+ }
+
for (key, value) in object.iter() {
match value {
- Value::Null => continue, // delete this entry
+ _ if key == "description" => continue, // skip description as we handle it above
+ Value::Null => continue, // delete this entry
Value::Bool(v) => writeln!(output, "{}: {}", key, v)?,
Value::String(v) => {
if v.as_bytes().contains(&b'\n') {
@@ -172,3 +191,36 @@ fn test() {
assert_eq!(config, NODE_CONFIG.as_bytes());
}
+
+#[test]
+fn test_with_comment() {
+ use proxmox_schema::ApiType;
+
+ // let's just reuse some schema we actually have available:
+ use crate::config::node::NodeConfig;
+
+ const NODE_INPUT: &str = "\
+ #this should\n\
+ #be included\n\
+ acme: account=pebble\n\
+ # this should not\n\
+ acmedomain0: test1.invalid.local,plugin=power\n\
+ acmedomain1: test2.invalid.local\n\
+ ";
+
+ const NODE_OUTPUT: &str = "\
+ #this should\n\
+ #be included\n\
+ acme: account=pebble\n\
+ acmedomain0: test1.invalid.local,plugin=power\n\
+ acmedomain1: test2.invalid.local\n\
+ ";
+
+ let data: NodeConfig = from_str(NODE_INPUT, &NodeConfig::API_SCHEMA)
+ .expect("failed to parse multi-line notes node config");
+
+ let config = to_bytes(&data, &NodeConfig::API_SCHEMA)
+ .expect("failed to serialize multi-line notes node config");
+
+ assert_eq!(config, NODE_OUTPUT.as_bytes());
+}
--
2.30.2
WARNING: multiple messages have this Message-ID
From: Stefan Sterz <s.sterz@proxmox.com>
To: pbs-devel@lists.proxmox.com, pve-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH proxmox-backup v3 1/6] fix #3067: api: add support for multi-line comments in node.cfg
Date: Fri, 4 Mar 2022 12:31:57 +0100 [thread overview]
Message-ID: <20220304113202.4137916-2-s.sterz@proxmox.com> (raw)
In-Reply-To: <20220304113202.4137916-1-s.sterz@proxmox.com>
add support for multi-line comments to node.cfg and the api, similar to
how pve handles multi-line comments
Signed-off-by: Stefan Sterz <s.sterz@proxmox.com>
---
pbs-api-types/src/lib.rs | 9 +++++++
src/api2/node/config.rs | 4 +++
src/config/node.rs | 14 +++++++++-
src/tools/config.rs | 56 ++++++++++++++++++++++++++++++++++++++--
4 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/pbs-api-types/src/lib.rs b/pbs-api-types/src/lib.rs
index 754e7b22..3b1fad2c 100644
--- a/pbs-api-types/src/lib.rs
+++ b/pbs-api-types/src/lib.rs
@@ -137,6 +137,8 @@ const_regex! {
pub SINGLE_LINE_COMMENT_REGEX = r"^[[:^cntrl:]]*$";
+ pub MULTI_LINE_COMMENT_REGEX = r"(?m)^([[:^cntrl:]]*)$";
+
pub BACKUP_REPO_URL_REGEX = concat!(
r"^^(?:(?:(",
USER_ID_REGEX_STR!(), "|", APITOKEN_ID_REGEX_STR!(),
@@ -273,6 +275,13 @@ pub const SINGLE_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (singl
.format(&SINGLE_LINE_COMMENT_FORMAT)
.schema();
+pub const MULTI_LINE_COMMENT_FORMAT: ApiStringFormat =
+ ApiStringFormat::Pattern(&MULTI_LINE_COMMENT_REGEX);
+
+pub const MULTI_LINE_COMMENT_SCHEMA: Schema = StringSchema::new("Comment (multiple lines).")
+ .format(&MULTI_LINE_COMMENT_FORMAT)
+ .schema();
+
pub const SUBSCRIPTION_KEY_SCHEMA: Schema = StringSchema::new("Proxmox Backup Server subscription key.")
.format(&SUBSCRIPTION_KEY_FORMAT)
.min_length(15)
diff --git a/src/api2/node/config.rs b/src/api2/node/config.rs
index 0a119354..3b267adc 100644
--- a/src/api2/node/config.rs
+++ b/src/api2/node/config.rs
@@ -64,6 +64,8 @@ pub enum DeletableProperty {
ciphers_tls_1_2,
/// Delete the default-lang property.
default_lang,
+ /// Delete any description
+ description,
}
#[api(
@@ -124,6 +126,7 @@ pub fn update_node_config(
DeletableProperty::ciphers_tls_1_3 => { config.ciphers_tls_1_3 = None; },
DeletableProperty::ciphers_tls_1_2 => { config.ciphers_tls_1_2 = None; },
DeletableProperty::default_lang => { config.default_lang = None; },
+ DeletableProperty::description => { config.description = None; },
}
}
}
@@ -139,6 +142,7 @@ pub fn update_node_config(
if update.ciphers_tls_1_3.is_some() { config.ciphers_tls_1_3 = update.ciphers_tls_1_3; }
if update.ciphers_tls_1_2.is_some() { config.ciphers_tls_1_2 = update.ciphers_tls_1_2; }
if update.default_lang.is_some() { config.default_lang = update.default_lang; }
+ if update.description.is_some() { config.description = update.description; }
crate::config::node::save_config(&config)?;
diff --git a/src/config/node.rs b/src/config/node.rs
index 0ba87450..ac6774e3 100644
--- a/src/config/node.rs
+++ b/src/config/node.rs
@@ -8,7 +8,11 @@ use proxmox_schema::{api, ApiStringFormat, ApiType, Updater};
use proxmox_http::ProxyConfig;
-use pbs_api_types::{EMAIL_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA, OPENSSL_CIPHERS_TLS_1_3_SCHEMA};
+use pbs_api_types::{
+ EMAIL_SCHEMA, MULTI_LINE_COMMENT_SCHEMA, OPENSSL_CIPHERS_TLS_1_2_SCHEMA,
+ OPENSSL_CIPHERS_TLS_1_3_SCHEMA,
+};
+
use pbs_buildcfg::configdir;
use pbs_config::{open_backup_lockfile, BackupLockGuard};
@@ -167,6 +171,10 @@ pub enum Translation {
"default-lang" : {
schema: Translation::API_SCHEMA,
optional: true,
+ },
+ "description" : {
+ optional: true,
+ schema: MULTI_LINE_COMMENT_SCHEMA,
}
},
)]
@@ -210,6 +218,10 @@ pub struct NodeConfig {
/// Default language used in the GUI
#[serde(skip_serializing_if = "Option::is_none")]
pub default_lang: Option<String>,
+
+ /// Node description
+ #[serde(skip_serializing_if = "Option::is_none")]
+ pub description: Option<String>,
}
impl NodeConfig {
diff --git a/src/tools/config.rs b/src/tools/config.rs
index f666a8ab..cc722094 100644
--- a/src/tools/config.rs
+++ b/src/tools/config.rs
@@ -31,8 +31,19 @@ pub fn value_from_str(input: &str, schema: &'static Schema) -> Result<Value, Err
let schema = object_schema(schema)?;
let mut config = Object::new();
+ let mut lines = input.lines().enumerate().peekable();
+ let mut description = String::new();
- for (lineno, line) in input.lines().enumerate() {
+ while let Some((_, line)) = lines.next_if(|(_, line)| line.starts_with('#')) {
+ description.push_str(&line[1..]);
+ description.push('\n');
+ }
+
+ if !description.is_empty() {
+ config.insert("description".to_string(), Value::String(description));
+ }
+
+ for (lineno, line) in lines {
let line = line.trim();
if line.starts_with('#') || line.is_empty() {
continue;
@@ -133,9 +144,17 @@ pub fn value_to_bytes(value: &Value, schema: &'static Schema) -> Result<Vec<u8>,
/// Note: the object must have already been verified at this point.
fn object_to_writer(output: &mut dyn Write, object: &Object) -> Result<(), Error> {
+ // special key `description` for multi-line notes, must be written before everything else
+ if let Some(Value::String(description)) = object.get("description") {
+ for lines in description.lines() {
+ writeln!(output, "#{}", lines)?;
+ }
+ }
+
for (key, value) in object.iter() {
match value {
- Value::Null => continue, // delete this entry
+ _ if key == "description" => continue, // skip description as we handle it above
+ Value::Null => continue, // delete this entry
Value::Bool(v) => writeln!(output, "{}: {}", key, v)?,
Value::String(v) => {
if v.as_bytes().contains(&b'\n') {
@@ -172,3 +191,36 @@ fn test() {
assert_eq!(config, NODE_CONFIG.as_bytes());
}
+
+#[test]
+fn test_with_comment() {
+ use proxmox_schema::ApiType;
+
+ // let's just reuse some schema we actually have available:
+ use crate::config::node::NodeConfig;
+
+ const NODE_INPUT: &str = "\
+ #this should\n\
+ #be included\n\
+ acme: account=pebble\n\
+ # this should not\n\
+ acmedomain0: test1.invalid.local,plugin=power\n\
+ acmedomain1: test2.invalid.local\n\
+ ";
+
+ const NODE_OUTPUT: &str = "\
+ #this should\n\
+ #be included\n\
+ acme: account=pebble\n\
+ acmedomain0: test1.invalid.local,plugin=power\n\
+ acmedomain1: test2.invalid.local\n\
+ ";
+
+ let data: NodeConfig = from_str(NODE_INPUT, &NodeConfig::API_SCHEMA)
+ .expect("failed to parse multi-line notes node config");
+
+ let config = to_bytes(&data, &NodeConfig::API_SCHEMA)
+ .expect("failed to serialize multi-line notes node config");
+
+ assert_eq!(config, NODE_OUTPUT.as_bytes());
+}
--
2.30.2
next prev parent reply other threads:[~2022-03-04 11:32 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-04 11:31 [pve-devel] [PATCH SERIES v3 0/6] fix #3607: add notes to functionality in webui Stefan Sterz
2022-03-04 11:31 ` [pbs-devel] " Stefan Sterz
2022-03-04 11:31 ` Stefan Sterz [this message]
2022-03-04 11:31 ` [pbs-devel] [PATCH proxmox-backup v3 1/6] fix #3067: api: add support for multi-line comments in node.cfg Stefan Sterz
2022-03-23 8:15 ` [pve-devel] " Wolfgang Bumiller
2022-03-23 8:15 ` Wolfgang Bumiller
2022-03-23 9:53 ` [pve-devel] applied: " Thomas Lamprecht
2022-03-23 9:53 ` [pbs-devel] applied: " Thomas Lamprecht
2022-03-04 11:31 ` [pve-devel] [PATCH proxmox-backup v3 2/6] fix #3607: docs: add markdown primer from pve to pbs Stefan Sterz
2022-03-04 11:31 ` [pbs-devel] " Stefan Sterz
2022-03-04 11:31 ` [pve-devel] [PATCH proxmox-backup v3 3/6] fix #3607: ui: add a separate notes view for longer markdown notes Stefan Sterz
2022-03-04 11:31 ` [pbs-devel] " Stefan Sterz
2022-03-23 11:08 ` [pve-devel] " Thomas Lamprecht
2022-03-23 11:08 ` [pbs-devel] " Thomas Lamprecht
2022-03-04 11:32 ` [pve-devel] [PATCH widget-toolkit v3 4/6] toolkit: add markdown based NotesView and NotesEdit Stefan Sterz
2022-03-04 11:32 ` [pbs-devel] " Stefan Sterz
2022-03-23 11:04 ` [pve-devel] " Thomas Lamprecht
2022-03-23 11:04 ` [pbs-devel] " Thomas Lamprecht
2022-03-04 11:32 ` [pve-devel] [PATCH proxmox-backup v3 5/6] fix #3607: ui: refactor notes by moving the panel/window to widget kit Stefan Sterz
2022-03-04 11:32 ` [pbs-devel] " Stefan Sterz
2022-03-23 11:09 ` [pve-devel] " Thomas Lamprecht
2022-03-23 11:09 ` [pbs-devel] " Thomas Lamprecht
2022-03-04 11:32 ` [pve-devel] [PATCH manager v3 6/6] ui: move NotesView panel and NotesEdit window " Stefan Sterz
2022-03-04 11:32 ` [pbs-devel] " Stefan Sterz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220304113202.4137916-2-s.sterz@proxmox.com \
--to=s.sterz@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.